mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-04 12:23:26 +01:00
Compare commits
21 Commits
2026-01-19
...
2026-01-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dd50aacd7 | ||
|
|
0dcb8b5ef7 | ||
|
|
a48435e064 | ||
|
|
cb2141ebe2 | ||
|
|
b1f21b4024 | ||
|
|
7699f4f6ad | ||
|
|
657a9629be | ||
|
|
d71f24bddb | ||
|
|
5a1c1e06f9 | ||
|
|
7146e8d5b9 | ||
|
|
a5dfa33af3 | ||
|
|
6dd5fbd7da | ||
|
|
718cda8eb1 | ||
|
|
ff5263981b | ||
|
|
785177fe29 | ||
|
|
5e7e7c884d | ||
|
|
97275d06ea | ||
|
|
0f15d81cd3 | ||
|
|
6712f6a9ca | ||
|
|
1816b0169e | ||
|
|
3f05972eb9 |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -10,8 +10,27 @@
|
||||
> [!CAUTION]
|
||||
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
|
||||
|
||||
## 2026-01-21
|
||||
|
||||
## 2026-01-20
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- dolibarr: switch mirror [@MickLesk](https://github.com/MickLesk) ([#11004](https://github.com/community-scripts/ProxmoxVE/pull/11004))
|
||||
- checkmk: reordner base function [@MickLesk](https://github.com/MickLesk) ([#10990](https://github.com/community-scripts/ProxmoxVE/pull/10990))
|
||||
- Homepage: preserve config directory during updates [@MickLesk](https://github.com/MickLesk) ([#10993](https://github.com/community-scripts/ProxmoxVE/pull/10993))
|
||||
- DiscoPanel: add go for update build process [@miausalvaje](https://github.com/miausalvaje) ([#10991](https://github.com/community-scripts/ProxmoxVE/pull/10991))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: add retry logic for template lock in LXC container creation [@MickLesk](https://github.com/MickLesk) ([#11002](https://github.com/community-scripts/ProxmoxVE/pull/11002))
|
||||
- core: implement ensure_profile_loaded function [@MickLesk](https://github.com/MickLesk) ([#10999](https://github.com/community-scripts/ProxmoxVE/pull/10999))
|
||||
- core: add input validations for several functions [@MickLesk](https://github.com/MickLesk) ([#10995](https://github.com/community-scripts/ProxmoxVE/pull/10995))
|
||||
|
||||
## 2026-01-19
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
@@ -54,9 +54,14 @@ function update_script() {
|
||||
cd /opt/discopanel/web/discopanel
|
||||
$STD npm install
|
||||
$STD npm run build
|
||||
msg_ok "Built Web Interface"
|
||||
|
||||
setup_go
|
||||
|
||||
msg_info "Building DiscoPanel"
|
||||
cd /opt/discopanel
|
||||
$STD go build -o discopanel cmd/discopanel/main.go
|
||||
msg_ok "Setup DiscoPanel"
|
||||
msg_ok "Built DiscoPanel"
|
||||
|
||||
msg_info "Restoring Data"
|
||||
mkdir -p /opt/discopanel/data
|
||||
|
||||
@@ -45,8 +45,11 @@ function update_script() {
|
||||
msg_ok "Stopped service"
|
||||
|
||||
cp /opt/homepage/.env /opt/homepage.env
|
||||
cp -r /opt/homepage/config /opt/homepage_config_backup
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "homepage" "gethomepage/homepage" "tarball"
|
||||
mv /opt/homepage.env /opt/homepage
|
||||
rm -rf /opt/homepage/config
|
||||
mv /opt/homepage_config_backup /opt/homepage/config
|
||||
|
||||
msg_info "Updating Homepage (Patience)"
|
||||
RELEASE=$(get_latest_github_release "gethomepage/homepage")
|
||||
|
||||
@@ -1,4 +1,199 @@
|
||||
[
|
||||
{
|
||||
"name": "semaphoreui/semaphore",
|
||||
"version": "v2.17.0-rc5",
|
||||
"date": "2026-01-20T23:36:16Z"
|
||||
},
|
||||
{
|
||||
"name": "ZoeyVid/NPMplus",
|
||||
"version": "2026-01-20-r2",
|
||||
"date": "2026-01-20T22:28:54Z"
|
||||
},
|
||||
{
|
||||
"name": "esphome/esphome",
|
||||
"version": "2025.12.7",
|
||||
"date": "2026-01-17T03:49:29Z"
|
||||
},
|
||||
{
|
||||
"name": "chrisbenincasa/tunarr",
|
||||
"version": "v1.2.0-dev.1",
|
||||
"date": "2026-01-20T21:46:14Z"
|
||||
},
|
||||
{
|
||||
"name": "SigNoz/signoz",
|
||||
"version": "v0.108.0-rc.1",
|
||||
"date": "2026-01-20T20:46:43Z"
|
||||
},
|
||||
{
|
||||
"name": "ollama/ollama",
|
||||
"version": "v0.14.3-rc2",
|
||||
"date": "2026-01-19T20:48:34Z"
|
||||
},
|
||||
{
|
||||
"name": "rcourtman/Pulse",
|
||||
"version": "v5.0.17",
|
||||
"date": "2026-01-20T19:07:30Z"
|
||||
},
|
||||
{
|
||||
"name": "firefly-iii/firefly-iii",
|
||||
"version": "v6.4.16",
|
||||
"date": "2026-01-17T07:54:15Z"
|
||||
},
|
||||
{
|
||||
"name": "netbox-community/netbox",
|
||||
"version": "v4.5.1",
|
||||
"date": "2026-01-20T19:45:05Z"
|
||||
},
|
||||
{
|
||||
"name": "Infisical/infisical",
|
||||
"version": "v0.155.7",
|
||||
"date": "2026-01-20T19:42:20Z"
|
||||
},
|
||||
{
|
||||
"name": "seerr-team/seerr",
|
||||
"version": "preview-availability-sync-fix",
|
||||
"date": "2026-01-20T19:12:59Z"
|
||||
},
|
||||
{
|
||||
"name": "nickheyer/discopanel",
|
||||
"version": "v1.0.24",
|
||||
"date": "2026-01-20T18:31:20Z"
|
||||
},
|
||||
{
|
||||
"name": "mysql/mysql-server",
|
||||
"version": "mysql-cluster-8.0.45",
|
||||
"date": "2026-01-20T18:27:03Z"
|
||||
},
|
||||
{
|
||||
"name": "element-hq/synapse",
|
||||
"version": "v1.145.0",
|
||||
"date": "2026-01-13T16:49:51Z"
|
||||
},
|
||||
{
|
||||
"name": "BerriAI/litellm",
|
||||
"version": "v1.81.0.rc.1",
|
||||
"date": "2026-01-20T16:55:00Z"
|
||||
},
|
||||
{
|
||||
"name": "chrisvel/tududi",
|
||||
"version": "v0.88.4",
|
||||
"date": "2026-01-20T16:02:12Z"
|
||||
},
|
||||
{
|
||||
"name": "gtsteffaniak/filebrowser",
|
||||
"version": "v1.1.1-stable",
|
||||
"date": "2026-01-12T23:25:10Z"
|
||||
},
|
||||
{
|
||||
"name": "mattermost/mattermost",
|
||||
"version": "@mattermost/client@11.3.0",
|
||||
"date": "2026-01-20T15:26:31Z"
|
||||
},
|
||||
{
|
||||
"name": "theonedev/onedev",
|
||||
"version": "v14.0.8",
|
||||
"date": "2026-01-20T15:10:44Z"
|
||||
},
|
||||
{
|
||||
"name": "metabase/metabase",
|
||||
"version": "v0.57.10",
|
||||
"date": "2026-01-20T14:55:34Z"
|
||||
},
|
||||
{
|
||||
"name": "meilisearch/meilisearch",
|
||||
"version": "latest",
|
||||
"date": "2026-01-20T14:25:19Z"
|
||||
},
|
||||
{
|
||||
"name": "sysadminsmedia/homebox",
|
||||
"version": "v0.23.0-rc.1",
|
||||
"date": "2026-01-20T14:19:56Z"
|
||||
},
|
||||
{
|
||||
"name": "apache/tomcat",
|
||||
"version": "9.0.114",
|
||||
"date": "2026-01-20T14:13:00Z"
|
||||
},
|
||||
{
|
||||
"name": "n8n-io/n8n",
|
||||
"version": "n8n@2.3.6",
|
||||
"date": "2026-01-16T15:00:42Z"
|
||||
},
|
||||
{
|
||||
"name": "jenkinsci/jenkins",
|
||||
"version": "jenkins-2.547",
|
||||
"date": "2026-01-20T13:46:00Z"
|
||||
},
|
||||
{
|
||||
"name": "docker/compose",
|
||||
"version": "v5.0.2",
|
||||
"date": "2026-01-20T12:57:53Z"
|
||||
},
|
||||
{
|
||||
"name": "dgtlmoon/changedetection.io",
|
||||
"version": "0.52.8",
|
||||
"date": "2026-01-20T12:36:05Z"
|
||||
},
|
||||
{
|
||||
"name": "lazy-media/Reactive-Resume",
|
||||
"version": "v1.2.7",
|
||||
"date": "2026-01-20T11:59:40Z"
|
||||
},
|
||||
{
|
||||
"name": "cloudflare/cloudflared",
|
||||
"version": "2026.1.1",
|
||||
"date": "2026-01-20T11:22:06Z"
|
||||
},
|
||||
{
|
||||
"name": "passbolt/passbolt_api",
|
||||
"version": "v5.9.0-test.1",
|
||||
"date": "2026-01-20T10:34:53Z"
|
||||
},
|
||||
{
|
||||
"name": "Luligu/matterbridge",
|
||||
"version": "3.5.0",
|
||||
"date": "2026-01-20T08:53:52Z"
|
||||
},
|
||||
{
|
||||
"name": "nzbgetcom/nzbget",
|
||||
"version": "v25.4",
|
||||
"date": "2025-10-09T10:27:01Z"
|
||||
},
|
||||
{
|
||||
"name": "openobserve/openobserve",
|
||||
"version": "v0.50.0",
|
||||
"date": "2026-01-20T07:34:31Z"
|
||||
},
|
||||
{
|
||||
"name": "HydroshieldMKII/Guardian",
|
||||
"version": "v1.3.4",
|
||||
"date": "2026-01-20T06:20:36Z"
|
||||
},
|
||||
{
|
||||
"name": "morpheus65535/bazarr",
|
||||
"version": "v1.5.4",
|
||||
"date": "2026-01-04T22:41:00Z"
|
||||
},
|
||||
{
|
||||
"name": "Comfy-Org/ComfyUI",
|
||||
"version": "v0.10.0",
|
||||
"date": "2026-01-20T03:40:18Z"
|
||||
},
|
||||
{
|
||||
"name": "diced/zipline",
|
||||
"version": "v4.4.1",
|
||||
"date": "2026-01-20T01:29:01Z"
|
||||
},
|
||||
{
|
||||
"name": "jeedom/core",
|
||||
"version": "4.5.2",
|
||||
"date": "2026-01-20T00:27:06Z"
|
||||
},
|
||||
{
|
||||
"name": "steveiliop56/tinyauth",
|
||||
"version": "v4.1.0",
|
||||
"date": "2025-11-23T12:13:34Z"
|
||||
},
|
||||
{
|
||||
"name": "binwiederhier/ntfy",
|
||||
"version": "v2.16.0",
|
||||
@@ -10,24 +205,14 @@
|
||||
"date": "2026-01-19T20:51:19Z"
|
||||
},
|
||||
{
|
||||
"name": "ollama/ollama",
|
||||
"version": "v0.14.3-rc2",
|
||||
"date": "2026-01-19T20:48:34Z"
|
||||
"name": "livebook-dev/livebook",
|
||||
"version": "nightly",
|
||||
"date": "2026-01-19T18:03:38Z"
|
||||
},
|
||||
{
|
||||
"name": "firefly-iii/firefly-iii",
|
||||
"version": "v6.4.16",
|
||||
"date": "2026-01-17T07:54:15Z"
|
||||
},
|
||||
{
|
||||
"name": "metabase/metabase",
|
||||
"version": "v0.58.x",
|
||||
"date": "2026-01-19T18:21:04Z"
|
||||
},
|
||||
{
|
||||
"name": "apache/tomcat",
|
||||
"version": "11.0.16",
|
||||
"date": "2026-01-19T18:15:05Z"
|
||||
"name": "keycloak/keycloak",
|
||||
"version": "26.4.8",
|
||||
"date": "2026-01-15T13:52:29Z"
|
||||
},
|
||||
{
|
||||
"name": "paperless-ngx/paperless-ngx",
|
||||
@@ -44,16 +229,6 @@
|
||||
"version": "server-v3.5.2",
|
||||
"date": "2025-12-19T21:28:55Z"
|
||||
},
|
||||
{
|
||||
"name": "meilisearch/meilisearch",
|
||||
"version": "prototype-v1.33.0-hannoy-better-linear-scanning.4",
|
||||
"date": "2026-01-19T16:37:18Z"
|
||||
},
|
||||
{
|
||||
"name": "Infisical/infisical",
|
||||
"version": "v0.155.6",
|
||||
"date": "2026-01-19T16:35:03Z"
|
||||
},
|
||||
{
|
||||
"name": "bunkerity/bunkerweb",
|
||||
"version": "v1.6.7",
|
||||
@@ -69,11 +244,6 @@
|
||||
"version": "pmm-6401-v1.134.0",
|
||||
"date": "2026-01-19T13:31:08Z"
|
||||
},
|
||||
{
|
||||
"name": "keycloak/keycloak",
|
||||
"version": "26.4.8",
|
||||
"date": "2026-01-15T13:52:29Z"
|
||||
},
|
||||
{
|
||||
"name": "crowdsecurity/crowdsec",
|
||||
"version": "v1.7.4",
|
||||
@@ -94,16 +264,6 @@
|
||||
"version": "v1.9.14",
|
||||
"date": "2026-01-19T09:16:56Z"
|
||||
},
|
||||
{
|
||||
"name": "dgtlmoon/changedetection.io",
|
||||
"version": "0.52.7",
|
||||
"date": "2026-01-19T08:38:05Z"
|
||||
},
|
||||
{
|
||||
"name": "morpheus65535/bazarr",
|
||||
"version": "v1.5.4",
|
||||
"date": "2026-01-04T22:41:00Z"
|
||||
},
|
||||
{
|
||||
"name": "Jackett/Jackett",
|
||||
"version": "v0.24.887",
|
||||
@@ -114,11 +274,6 @@
|
||||
"version": "v1.9.0",
|
||||
"date": "2026-01-19T05:46:09Z"
|
||||
},
|
||||
{
|
||||
"name": "nickheyer/discopanel",
|
||||
"version": "v1.0.23",
|
||||
"date": "2026-01-19T05:14:43Z"
|
||||
},
|
||||
{
|
||||
"name": "9001/copyparty",
|
||||
"version": "v1.20.2",
|
||||
@@ -134,16 +289,6 @@
|
||||
"version": "2.1.0rc1",
|
||||
"date": "2026-01-19T00:48:21Z"
|
||||
},
|
||||
{
|
||||
"name": "steveiliop56/tinyauth",
|
||||
"version": "v4.1.0",
|
||||
"date": "2025-11-23T12:13:34Z"
|
||||
},
|
||||
{
|
||||
"name": "jeedom/core",
|
||||
"version": "4.5.2",
|
||||
"date": "2026-01-19T00:27:05Z"
|
||||
},
|
||||
{
|
||||
"name": "Kareadita/Kavita",
|
||||
"version": "v0.8.9.1",
|
||||
@@ -164,11 +309,6 @@
|
||||
"version": "v2.5.0",
|
||||
"date": "2026-01-18T22:16:38Z"
|
||||
},
|
||||
{
|
||||
"name": "seerr-team/seerr",
|
||||
"version": "preview-remonitor-sonarr-episodes",
|
||||
"date": "2026-01-18T20:33:38Z"
|
||||
},
|
||||
{
|
||||
"name": "fccview/jotty",
|
||||
"version": "1.18.0",
|
||||
@@ -194,11 +334,6 @@
|
||||
"version": "2.4",
|
||||
"date": "2026-01-18T12:12:02Z"
|
||||
},
|
||||
{
|
||||
"name": "BerriAI/litellm",
|
||||
"version": "v1.81.0-nightly",
|
||||
"date": "2026-01-18T04:06:15Z"
|
||||
},
|
||||
{
|
||||
"name": "hyperion-project/hyperion.ng",
|
||||
"version": "2.1.1",
|
||||
@@ -209,16 +344,6 @@
|
||||
"version": "v7.14.2",
|
||||
"date": "2026-01-18T00:26:09Z"
|
||||
},
|
||||
{
|
||||
"name": "chrisbenincasa/tunarr",
|
||||
"version": "v1.1.1",
|
||||
"date": "2026-01-17T22:35:09Z"
|
||||
},
|
||||
{
|
||||
"name": "ZoeyVid/NPMplus",
|
||||
"version": "2026-01-17-r3",
|
||||
"date": "2026-01-17T21:45:17Z"
|
||||
},
|
||||
{
|
||||
"name": "outline/outline",
|
||||
"version": "v1.3.0",
|
||||
@@ -244,11 +369,6 @@
|
||||
"version": "v6.13.6",
|
||||
"date": "2025-11-04T13:35:35Z"
|
||||
},
|
||||
{
|
||||
"name": "esphome/esphome",
|
||||
"version": "2025.12.7",
|
||||
"date": "2026-01-17T03:49:29Z"
|
||||
},
|
||||
{
|
||||
"name": "coder/code-server",
|
||||
"version": "v4.108.1",
|
||||
@@ -269,21 +389,6 @@
|
||||
"version": "v1.50.1",
|
||||
"date": "2026-01-16T19:27:38Z"
|
||||
},
|
||||
{
|
||||
"name": "livebook-dev/livebook",
|
||||
"version": "v0.18.3",
|
||||
"date": "2026-01-14T21:50:55Z"
|
||||
},
|
||||
{
|
||||
"name": "cloudflare/cloudflared",
|
||||
"version": "2026.1.0",
|
||||
"date": "2026-01-16T17:48:15Z"
|
||||
},
|
||||
{
|
||||
"name": "n8n-io/n8n",
|
||||
"version": "n8n@2.3.6",
|
||||
"date": "2026-01-16T15:00:42Z"
|
||||
},
|
||||
{
|
||||
"name": "emqx/emqx",
|
||||
"version": "6.0.2",
|
||||
@@ -319,11 +424,6 @@
|
||||
"version": "v0.13.6",
|
||||
"date": "2026-01-15T23:34:51Z"
|
||||
},
|
||||
{
|
||||
"name": "semaphoreui/semaphore",
|
||||
"version": "v2.17.0-rc3",
|
||||
"date": "2026-01-15T21:30:26Z"
|
||||
},
|
||||
{
|
||||
"name": "azukaar/Cosmos-Server",
|
||||
"version": "v0.20.0",
|
||||
@@ -339,11 +439,6 @@
|
||||
"version": "v2.3.0",
|
||||
"date": "2026-01-15T19:29:02Z"
|
||||
},
|
||||
{
|
||||
"name": "Comfy-Org/ComfyUI",
|
||||
"version": "v0.9.2",
|
||||
"date": "2026-01-15T17:55:40Z"
|
||||
},
|
||||
{
|
||||
"name": "zwave-js/zwave-js-ui",
|
||||
"version": "v11.10.1",
|
||||
@@ -359,26 +454,11 @@
|
||||
"version": "0.24.3",
|
||||
"date": "2026-01-15T14:40:15Z"
|
||||
},
|
||||
{
|
||||
"name": "openobserve/openobserve",
|
||||
"version": "v0.50.0-rc3",
|
||||
"date": "2026-01-15T13:57:37Z"
|
||||
},
|
||||
{
|
||||
"name": "readeck/readeck",
|
||||
"version": "0.21.6",
|
||||
"date": "2026-01-15T11:18:58Z"
|
||||
},
|
||||
{
|
||||
"name": "mattermost/mattermost",
|
||||
"version": "v10.11.10",
|
||||
"date": "2026-01-15T10:36:07Z"
|
||||
},
|
||||
{
|
||||
"name": "SigNoz/signoz",
|
||||
"version": "v0.107.0",
|
||||
"date": "2026-01-15T06:50:08Z"
|
||||
},
|
||||
{
|
||||
"name": "zitadel/zitadel",
|
||||
"version": "v4.9.1",
|
||||
@@ -474,11 +554,6 @@
|
||||
"version": "v0.5.5",
|
||||
"date": "2026-01-13T17:03:32Z"
|
||||
},
|
||||
{
|
||||
"name": "element-hq/synapse",
|
||||
"version": "v1.145.0",
|
||||
"date": "2026-01-13T16:49:51Z"
|
||||
},
|
||||
{
|
||||
"name": "LimeSurvey/LimeSurvey",
|
||||
"version": "6.16.3+251215",
|
||||
@@ -489,16 +564,6 @@
|
||||
"version": "v0.16.6",
|
||||
"date": "2026-01-13T10:28:14Z"
|
||||
},
|
||||
{
|
||||
"name": "jenkinsci/jenkins",
|
||||
"version": "jenkins-2.546",
|
||||
"date": "2026-01-13T10:08:09Z"
|
||||
},
|
||||
{
|
||||
"name": "Luligu/matterbridge",
|
||||
"version": "3.4.7",
|
||||
"date": "2026-01-13T07:28:02Z"
|
||||
},
|
||||
{
|
||||
"name": "henrygd/beszel",
|
||||
"version": "v0.18.2",
|
||||
@@ -514,11 +579,6 @@
|
||||
"version": "26.1.1",
|
||||
"date": "2026-01-12T23:26:02Z"
|
||||
},
|
||||
{
|
||||
"name": "gtsteffaniak/filebrowser",
|
||||
"version": "v1.1.1-stable",
|
||||
"date": "2026-01-12T23:25:10Z"
|
||||
},
|
||||
{
|
||||
"name": "influxdata/influxdb",
|
||||
"version": "v2.8.0",
|
||||
@@ -534,11 +594,6 @@
|
||||
"version": "v1.7.10",
|
||||
"date": "2026-01-12T20:50:50Z"
|
||||
},
|
||||
{
|
||||
"name": "rcourtman/Pulse",
|
||||
"version": "v5.0.16",
|
||||
"date": "2026-01-12T20:18:34Z"
|
||||
},
|
||||
{
|
||||
"name": "release-argus/Argus",
|
||||
"version": "0.29.2",
|
||||
@@ -624,11 +679,6 @@
|
||||
"version": "v0.14.1",
|
||||
"date": "2024-08-29T22:32:51Z"
|
||||
},
|
||||
{
|
||||
"name": "theonedev/onedev",
|
||||
"version": "v14.0.7",
|
||||
"date": "2026-01-10T10:31:47Z"
|
||||
},
|
||||
{
|
||||
"name": "Kozea/Radicale",
|
||||
"version": "v3.6.0",
|
||||
@@ -759,11 +809,6 @@
|
||||
"version": "2.46.0",
|
||||
"date": "2026-01-07T00:19:31Z"
|
||||
},
|
||||
{
|
||||
"name": "netbox-community/netbox",
|
||||
"version": "v4.5.0",
|
||||
"date": "2026-01-06T21:14:27Z"
|
||||
},
|
||||
{
|
||||
"name": "caddyserver/caddy",
|
||||
"version": "v2.10.2",
|
||||
@@ -874,16 +919,6 @@
|
||||
"version": "v4.7.0",
|
||||
"date": "2025-12-27T20:37:54Z"
|
||||
},
|
||||
{
|
||||
"name": "sysadminsmedia/homebox",
|
||||
"version": "v0.22.3",
|
||||
"date": "2025-12-26T22:31:20Z"
|
||||
},
|
||||
{
|
||||
"name": "HydroshieldMKII/Guardian",
|
||||
"version": "v1.3.3",
|
||||
"date": "2025-12-25T20:19:52Z"
|
||||
},
|
||||
{
|
||||
"name": "matze/wastebin",
|
||||
"version": "3.4.0",
|
||||
@@ -919,11 +954,6 @@
|
||||
"version": "v5.7",
|
||||
"date": "2025-12-23T14:53:51Z"
|
||||
},
|
||||
{
|
||||
"name": "nzbgetcom/nzbget",
|
||||
"version": "v25.4",
|
||||
"date": "2025-10-09T10:27:01Z"
|
||||
},
|
||||
{
|
||||
"name": "itsmng/itsm-ng",
|
||||
"version": "v1.6.11",
|
||||
@@ -944,16 +974,6 @@
|
||||
"version": "v4.0.16.2944",
|
||||
"date": "2025-11-05T01:56:48Z"
|
||||
},
|
||||
{
|
||||
"name": "chrisvel/tududi",
|
||||
"version": "v0.88.2",
|
||||
"date": "2025-12-22T14:36:59Z"
|
||||
},
|
||||
{
|
||||
"name": "passbolt/passbolt_api",
|
||||
"version": "v5.8.0",
|
||||
"date": "2025-12-22T10:12:48Z"
|
||||
},
|
||||
{
|
||||
"name": "benjaminjonard/koillection",
|
||||
"version": "1.7.1",
|
||||
@@ -1009,11 +1029,6 @@
|
||||
"version": "v1.25.3",
|
||||
"date": "2025-12-18T18:11:48Z"
|
||||
},
|
||||
{
|
||||
"name": "docker/compose",
|
||||
"version": "v5.0.1",
|
||||
"date": "2025-12-18T14:22:38Z"
|
||||
},
|
||||
{
|
||||
"name": "juanfont/headscale",
|
||||
"version": "v0.27.1",
|
||||
@@ -1059,11 +1074,6 @@
|
||||
"version": "v1.13.2",
|
||||
"date": "2025-12-13T22:59:03Z"
|
||||
},
|
||||
{
|
||||
"name": "diced/zipline",
|
||||
"version": "v4.4.0",
|
||||
"date": "2025-12-13T22:49:07Z"
|
||||
},
|
||||
{
|
||||
"name": "WGDashboard/WGDashboard",
|
||||
"version": "v4.3.1",
|
||||
@@ -1424,11 +1434,6 @@
|
||||
"version": "v2.2.2",
|
||||
"date": "2025-10-06T21:31:07Z"
|
||||
},
|
||||
{
|
||||
"name": "mysql/mysql-server",
|
||||
"version": "mysql-cluster-7.6.36",
|
||||
"date": "2025-10-06T15:19:49Z"
|
||||
},
|
||||
{
|
||||
"name": "jordan-dalby/ByteStash",
|
||||
"version": "v1.5.9",
|
||||
@@ -1444,11 +1449,6 @@
|
||||
"version": "v1.11.1",
|
||||
"date": "2025-09-30T00:24:16Z"
|
||||
},
|
||||
{
|
||||
"name": "lazy-media/Reactive-Resume",
|
||||
"version": "v1.2.6",
|
||||
"date": "2025-09-28T18:09:21Z"
|
||||
},
|
||||
{
|
||||
"name": "Pf2eToolsOrg/Pf2eTools",
|
||||
"version": "v0.10.1",
|
||||
|
||||
@@ -21,9 +21,6 @@ rm -rf /opt/checkmk.deb
|
||||
echo "${RELEASE}" >"/opt/checkmk_version.txt"
|
||||
msg_ok "Installed Checkmk"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
msg_info "Creating Service"
|
||||
SITE_NAME="monitoring"
|
||||
$STD omd create "$SITE_NAME"
|
||||
@@ -42,3 +39,5 @@ $STD omd start "$SITE_NAME"
|
||||
msg_ok "Created Service"
|
||||
|
||||
cleanup_lxc
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
@@ -34,7 +34,7 @@ msg_info "Setup Dolibarr"
|
||||
BASE="https://sourceforge.net/projects/dolibarr/files/Dolibarr%20installer%20for%20Debian-Ubuntu%20(DoliDeb)/"
|
||||
RELEASE=$(curl -fsSL "$BASE" | grep -oP '(?<=/Dolibarr%20installer%20for%20Debian-Ubuntu%20%28DoliDeb%29/)\d+(\.\d+)+(?=/)' | sort -V | tail -n1)
|
||||
FILE=$(curl -fsSL "${BASE}${RELEASE}/" | grep -oP 'dolibarr_[^"]+_all.deb' | head -n1)
|
||||
curl -fsSL "https://netcologne.dl.sourceforge.net/project/dolibarr/Dolibarr%20installer%20for%20Debian-Ubuntu%20(DoliDeb)/${RELEASE}/${FILE}?viasf=1" -o ""$FILE""
|
||||
curl -fsSL "https://altushost-swe.dl.sourceforge.net/project/dolibarr/Dolibarr%20installer%20for%20Debian-Ubuntu%20(DoliDeb)/${RELEASE}/${FILE}?viasf=1" -o ""$FILE""
|
||||
echo "dolibarr dolibarr/reconfigure-webserver multiselect apache2" | debconf-set-selections
|
||||
$STD apt-get install ./$FILE -y
|
||||
$STD apt install -f
|
||||
|
||||
595
misc/build.func
595
misc/build.func
@@ -357,6 +357,268 @@ validate_hostname() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_mac_address()
|
||||
#
|
||||
# - Validates MAC address format (XX:XX:XX:XX:XX:XX)
|
||||
# - Empty value is allowed (auto-generated)
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_mac_address() {
|
||||
local mac="$1"
|
||||
[[ -z "$mac" ]] && return 0
|
||||
if [[ ! "$mac" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_vlan_tag()
|
||||
#
|
||||
# - Validates VLAN tag (1-4094)
|
||||
# - Empty value is allowed (no VLAN)
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_vlan_tag() {
|
||||
local vlan="$1"
|
||||
[[ -z "$vlan" ]] && return 0
|
||||
if ! [[ "$vlan" =~ ^[0-9]+$ ]] || ((vlan < 1 || vlan > 4094)); then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_mtu()
|
||||
#
|
||||
# - Validates MTU size (576-65535, common values: 1500, 9000)
|
||||
# - Empty value is allowed (default 1500)
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_mtu() {
|
||||
local mtu="$1"
|
||||
[[ -z "$mtu" ]] && return 0
|
||||
if ! [[ "$mtu" =~ ^[0-9]+$ ]] || ((mtu < 576 || mtu > 65535)); then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_ipv6_address()
|
||||
#
|
||||
# - Validates IPv6 address with optional CIDR notation
|
||||
# - Supports compressed (::) and full notation
|
||||
# - Empty value is allowed
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_ipv6_address() {
|
||||
local ipv6="$1"
|
||||
[[ -z "$ipv6" ]] && return 0
|
||||
|
||||
# Extract address and CIDR
|
||||
local addr="${ipv6%%/*}"
|
||||
local cidr="${ipv6##*/}"
|
||||
|
||||
# Validate CIDR if present (1-128)
|
||||
if [[ "$ipv6" == */* ]]; then
|
||||
if ! [[ "$cidr" =~ ^[0-9]+$ ]] || ((cidr < 1 || cidr > 128)); then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Basic IPv6 validation - check for valid characters and structure
|
||||
# Must contain only hex digits and colons
|
||||
if [[ ! "$addr" =~ ^[0-9a-fA-F:]+$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Must contain at least one colon
|
||||
if [[ ! "$addr" == *:* ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check for valid double-colon usage (only one :: allowed)
|
||||
if [[ "$addr" == *::*::* ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check that no segment exceeds 4 hex chars
|
||||
local IFS=':'
|
||||
local -a segments
|
||||
read -ra segments <<< "$addr"
|
||||
for seg in "${segments[@]}"; do
|
||||
if [[ ${#seg} -gt 4 ]]; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_bridge()
|
||||
#
|
||||
# - Validates that network bridge exists and is active
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_bridge() {
|
||||
local bridge="$1"
|
||||
[[ -z "$bridge" ]] && return 1
|
||||
|
||||
# Check if bridge interface exists
|
||||
if ! ip link show "$bridge" &>/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_gateway_in_subnet()
|
||||
#
|
||||
# - Validates that gateway IP is in the same subnet as static IP
|
||||
# - Arguments: static_ip (with CIDR), gateway_ip
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_gateway_in_subnet() {
|
||||
local static_ip="$1"
|
||||
local gateway="$2"
|
||||
|
||||
[[ -z "$static_ip" || -z "$gateway" ]] && return 0
|
||||
|
||||
# Extract IP and CIDR
|
||||
local ip="${static_ip%%/*}"
|
||||
local cidr="${static_ip##*/}"
|
||||
|
||||
# Convert CIDR to netmask bits
|
||||
local mask=$((0xFFFFFFFF << (32 - cidr) & 0xFFFFFFFF))
|
||||
|
||||
# Convert IPs to integers
|
||||
local IFS='.'
|
||||
read -r i1 i2 i3 i4 <<< "$ip"
|
||||
read -r g1 g2 g3 g4 <<< "$gateway"
|
||||
|
||||
local ip_int=$(( (i1 << 24) + (i2 << 16) + (i3 << 8) + i4 ))
|
||||
local gw_int=$(( (g1 << 24) + (g2 << 16) + (g3 << 8) + g4 ))
|
||||
|
||||
# Check if both are in same network
|
||||
if (( (ip_int & mask) != (gw_int & mask) )); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_ip_address()
|
||||
#
|
||||
# - Validates IPv4 address with CIDR notation
|
||||
# - Checks each octet is 0-255
|
||||
# - Checks CIDR is 1-32
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_ip_address() {
|
||||
local ip="$1"
|
||||
[[ -z "$ip" ]] && return 1
|
||||
|
||||
# Check format with CIDR
|
||||
if [[ ! "$ip" =~ ^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local o1="${BASH_REMATCH[1]}"
|
||||
local o2="${BASH_REMATCH[2]}"
|
||||
local o3="${BASH_REMATCH[3]}"
|
||||
local o4="${BASH_REMATCH[4]}"
|
||||
local cidr="${BASH_REMATCH[5]}"
|
||||
|
||||
# Validate octets (0-255)
|
||||
for octet in "$o1" "$o2" "$o3" "$o4"; do
|
||||
if ((octet > 255)); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Validate CIDR (1-32)
|
||||
if ((cidr < 1 || cidr > 32)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_gateway_ip()
|
||||
#
|
||||
# - Validates gateway IPv4 address (without CIDR)
|
||||
# - Checks each octet is 0-255
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_gateway_ip() {
|
||||
local ip="$1"
|
||||
[[ -z "$ip" ]] && return 0
|
||||
|
||||
# Check format without CIDR
|
||||
if [[ ! "$ip" =~ ^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local o1="${BASH_REMATCH[1]}"
|
||||
local o2="${BASH_REMATCH[2]}"
|
||||
local o3="${BASH_REMATCH[3]}"
|
||||
local o4="${BASH_REMATCH[4]}"
|
||||
|
||||
# Validate octets (0-255)
|
||||
for octet in "$o1" "$o2" "$o3" "$o4"; do
|
||||
if ((octet > 255)); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_timezone()
|
||||
#
|
||||
# - Validates timezone string against system zoneinfo
|
||||
# - Empty value or "host" is allowed
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_timezone() {
|
||||
local tz="$1"
|
||||
[[ -z "$tz" || "$tz" == "host" ]] && return 0
|
||||
|
||||
# Check if timezone file exists
|
||||
if [[ ! -f "/usr/share/zoneinfo/$tz" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# validate_tags()
|
||||
#
|
||||
# - Validates Proxmox tags format
|
||||
# - Only alphanumeric, hyphens, underscores, and semicolons allowed
|
||||
# - Empty value is allowed
|
||||
# - Returns 0 if valid, 1 if invalid
|
||||
# ------------------------------------------------------------------------------
|
||||
validate_tags() {
|
||||
local tags="$1"
|
||||
[[ -z "$tags" ]] && return 0
|
||||
|
||||
# Tags can only contain alphanumeric, -, _, and ; (separator)
|
||||
if [[ ! "$tags" =~ ^[a-zA-Z0-9_\;-]+$ ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# find_host_ssh_keys()
|
||||
#
|
||||
@@ -772,6 +1034,119 @@ load_vars_file() {
|
||||
# Trim trailing whitespace
|
||||
var_val="${var_val%"${var_val##*[![:space:]]}"}"
|
||||
|
||||
# Validate values before setting (skip empty values - they use defaults)
|
||||
if [[ -n "$var_val" ]]; then
|
||||
case "$var_key" in
|
||||
var_mac)
|
||||
if ! validate_mac_address "$var_val"; then
|
||||
msg_warn "Invalid MAC address '$var_val' in $file, ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_vlan)
|
||||
if ! validate_vlan_tag "$var_val"; then
|
||||
msg_warn "Invalid VLAN tag '$var_val' in $file (must be 1-4094), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_mtu)
|
||||
if ! validate_mtu "$var_val"; then
|
||||
msg_warn "Invalid MTU '$var_val' in $file (must be 576-65535), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_tags)
|
||||
if ! validate_tags "$var_val"; then
|
||||
msg_warn "Invalid tags '$var_val' in $file (alphanumeric, -, _, ; only), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_timezone)
|
||||
if ! validate_timezone "$var_val"; then
|
||||
msg_warn "Invalid timezone '$var_val' in $file, ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_brg)
|
||||
if ! validate_bridge "$var_val"; then
|
||||
msg_warn "Bridge '$var_val' not found in $file, ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_gateway)
|
||||
if ! validate_gateway_ip "$var_val"; then
|
||||
msg_warn "Invalid gateway IP '$var_val' in $file, ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_hostname)
|
||||
if ! validate_hostname "$var_val"; then
|
||||
msg_warn "Invalid hostname '$var_val' in $file, ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_cpu)
|
||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1 || var_val > 128)); then
|
||||
msg_warn "Invalid CPU count '$var_val' in $file (must be 1-128), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_ram)
|
||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 256)); then
|
||||
msg_warn "Invalid RAM '$var_val' in $file (must be >= 256 MiB), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_disk)
|
||||
if ! [[ "$var_val" =~ ^[0-9]+$ ]] || ((var_val < 1)); then
|
||||
msg_warn "Invalid disk size '$var_val' in $file (must be >= 1 GB), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_unprivileged)
|
||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||
msg_warn "Invalid unprivileged value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_nesting)
|
||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||
msg_warn "Invalid nesting value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_keyctl)
|
||||
if [[ "$var_val" != "0" && "$var_val" != "1" ]]; then
|
||||
msg_warn "Invalid keyctl value '$var_val' in $file (must be 0 or 1), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_net)
|
||||
# var_net can be: dhcp, static IP/CIDR, or IP range
|
||||
if [[ "$var_val" != "dhcp" ]]; then
|
||||
if is_ip_range "$var_val"; then
|
||||
: # IP range is valid, will be resolved at runtime
|
||||
elif ! validate_ip_address "$var_val"; then
|
||||
msg_warn "Invalid network '$var_val' in $file (must be dhcp or IP/CIDR), ignoring"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
var_fuse|var_tun|var_gpu|var_ssh|var_verbose|var_protection)
|
||||
if [[ "$var_val" != "yes" && "$var_val" != "no" ]]; then
|
||||
msg_warn "Invalid boolean '$var_val' for $var_key in $file (must be yes/no), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_ipv6_method)
|
||||
if [[ "$var_val" != "auto" && "$var_val" != "dhcp" && "$var_val" != "static" && "$var_val" != "none" ]]; then
|
||||
msg_warn "Invalid IPv6 method '$var_val' in $file (must be auto/dhcp/static/none), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Set variable: force mode overrides existing, otherwise only set if empty
|
||||
if [[ "$force" == "yes" ]]; then
|
||||
export "${var_key}=${var_val}"
|
||||
@@ -1612,8 +1987,14 @@ advanced_settings() {
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
8)
|
||||
if [[ ${#BRIDGE_MENU_OPTIONS[@]} -eq 0 ]]; then
|
||||
_bridge="vmbr0"
|
||||
((STEP++))
|
||||
# Validate default bridge exists
|
||||
if validate_bridge "vmbr0"; then
|
||||
_bridge="vmbr0"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Default bridge 'vmbr0' not found!\n\nPlease configure a network bridge in Proxmox first." 10 58
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "NETWORK BRIDGE" \
|
||||
@@ -1621,8 +2002,13 @@ advanced_settings() {
|
||||
--menu "\nSelect network bridge:" 16 58 6 \
|
||||
"${BRIDGE_MENU_OPTIONS[@]}" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_bridge="${result:-vmbr0}"
|
||||
((STEP++))
|
||||
local bridge_test="${result:-vmbr0}"
|
||||
if validate_bridge "$bridge_test"; then
|
||||
_bridge="$bridge_test"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Bridge '$bridge_test' is not available or not active." 8 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -1650,7 +2036,7 @@ advanced_settings() {
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nEnter Static IPv4 CIDR Address\n(e.g. 192.168.1.100/24)" 12 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [[ "$static_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then
|
||||
if validate_ip_address "$static_ip"; then
|
||||
# Get gateway
|
||||
local gateway_ip
|
||||
if gateway_ip=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
@@ -1658,16 +2044,21 @@ advanced_settings() {
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nEnter Gateway IP address" 10 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [[ "$gateway_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
_net="$static_ip"
|
||||
_gate=",gw=$gateway_ip"
|
||||
((STEP++))
|
||||
if validate_gateway_ip "$gateway_ip"; then
|
||||
# Validate gateway is in same subnet
|
||||
if validate_gateway_in_subnet "$static_ip" "$gateway_ip"; then
|
||||
_net="$static_ip"
|
||||
_gate=",gw=$gateway_ip"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Gateway is not in the same subnet as the static IP.\n\nStatic IP: $static_ip\nGateway: $gateway_ip" 10 58
|
||||
fi
|
||||
else
|
||||
whiptail --msgbox "Invalid Gateway IP format." 8 58
|
||||
whiptail --msgbox "Invalid Gateway IP format.\n\nEach octet must be 0-255.\nExample: 192.168.1.1" 10 58
|
||||
fi
|
||||
fi
|
||||
else
|
||||
whiptail --msgbox "Invalid IPv4 CIDR format.\nExample: 192.168.1.100/24" 8 58
|
||||
whiptail --msgbox "Invalid IPv4 CIDR format.\n\nEach octet must be 0-255.\nCIDR must be 1-32.\nExample: 192.168.1.100/24" 12 58
|
||||
fi
|
||||
fi
|
||||
elif [[ "$result" == "range" ]]; then
|
||||
@@ -1691,12 +2082,17 @@ advanced_settings() {
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nFound free IP: $NET_RESOLVED\n\nEnter Gateway IP address" 12 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [[ "$gateway_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
_net="$NET_RESOLVED"
|
||||
_gate=",gw=$gateway_ip"
|
||||
((STEP++))
|
||||
if validate_gateway_ip "$gateway_ip"; then
|
||||
# Validate gateway is in same subnet
|
||||
if validate_gateway_in_subnet "$NET_RESOLVED" "$gateway_ip"; then
|
||||
_net="$NET_RESOLVED"
|
||||
_gate=",gw=$gateway_ip"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Gateway is not in the same subnet as the IP.\n\nIP: $NET_RESOLVED\nGateway: $gateway_ip" 10 58
|
||||
fi
|
||||
else
|
||||
whiptail --msgbox "Invalid Gateway IP format." 8 58
|
||||
whiptail --msgbox "Invalid Gateway IP format.\n\nEach octet must be 0-255.\nExample: 192.168.1.1" 10 58
|
||||
fi
|
||||
fi
|
||||
else
|
||||
@@ -1739,16 +2135,33 @@ advanced_settings() {
|
||||
--title "STATIC IPv6 ADDRESS" \
|
||||
--inputbox "\nEnter IPv6 CIDR address\n(e.g. 2001:db8::1/64)" 12 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [[ "$ipv6_addr" =~ ^([0-9a-fA-F:]+:+)+[0-9a-fA-F]+(/[0-9]{1,3})$ ]]; then
|
||||
if validate_ipv6_address "$ipv6_addr"; then
|
||||
_ipv6_addr="$ipv6_addr"
|
||||
# Optional gateway
|
||||
_ipv6_gate=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "IPv6 GATEWAY" \
|
||||
--inputbox "\nEnter IPv6 gateway (optional, leave blank for none)" 10 58 "" \
|
||||
3>&1 1>&2 2>&3) || true
|
||||
((STEP++))
|
||||
# Optional gateway - loop until valid or empty
|
||||
local ipv6_gw_valid=false
|
||||
while [[ "$ipv6_gw_valid" == "false" ]]; do
|
||||
local ipv6_gw
|
||||
ipv6_gw=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "IPv6 GATEWAY" \
|
||||
--inputbox "\nEnter IPv6 gateway (optional, leave blank for none)" 10 58 "" \
|
||||
3>&1 1>&2 2>&3) || true
|
||||
# Validate gateway if provided
|
||||
if [[ -n "$ipv6_gw" ]]; then
|
||||
if validate_ipv6_address "$ipv6_gw"; then
|
||||
_ipv6_gate="$ipv6_gw"
|
||||
ipv6_gw_valid=true
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid IPv6 gateway format.\n\nExample: 2001:db8::1" 8 58
|
||||
fi
|
||||
else
|
||||
_ipv6_gate=""
|
||||
ipv6_gw_valid=true
|
||||
((STEP++))
|
||||
fi
|
||||
done
|
||||
else
|
||||
whiptail --msgbox "Invalid IPv6 CIDR format." 8 58
|
||||
whiptail --msgbox "Invalid IPv6 CIDR format.\n\nExample: 2001:db8::1/64\nCIDR must be 1-128." 10 58
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
@@ -1781,10 +2194,14 @@ advanced_settings() {
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "MTU SIZE" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nSet Interface MTU Size\n(leave blank for default 1500)" 12 58 "" \
|
||||
--inputbox "\nSet Interface MTU Size\n(leave blank for default 1500, common values: 1500, 9000)" 12 62 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_mtu="$result"
|
||||
((STEP++))
|
||||
if validate_mtu "$result"; then
|
||||
_mtu="$result"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid MTU size.\n\nMTU must be between 576 and 65535.\nCommon values: 1500 (default), 9000 (jumbo frames)" 10 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -1829,10 +2246,14 @@ advanced_settings() {
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "MAC ADDRESS" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nSet MAC Address\n(leave blank for auto-generated)" 12 58 "" \
|
||||
--inputbox "\nSet MAC Address\n(leave blank for auto-generated, format: XX:XX:XX:XX:XX:XX)" 12 62 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_mac="$result"
|
||||
((STEP++))
|
||||
if validate_mac_address "$result"; then
|
||||
_mac="$result"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid MAC address format.\n\nRequired format: XX:XX:XX:XX:XX:XX\nExample: 02:00:00:00:00:01" 10 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -1845,10 +2266,14 @@ advanced_settings() {
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "VLAN TAG" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nSet VLAN Tag\n(leave blank for no VLAN)" 12 58 "" \
|
||||
--inputbox "\nSet VLAN Tag (1-4094)\n(leave blank for no VLAN)" 12 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_vlan="$result"
|
||||
((STEP++))
|
||||
if validate_vlan_tag "$result"; then
|
||||
_vlan="$result"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid VLAN tag.\n\nVLAN must be a number between 1 and 4094." 8 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -1861,11 +2286,16 @@ advanced_settings() {
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "CONTAINER TAGS" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nSet Custom Tags (semicolon-separated)\n(remove all for no tags)" 12 58 "$_tags" \
|
||||
--inputbox "\nSet Custom Tags (semicolon-separated)\n(alphanumeric, hyphens, underscores only)" 12 58 "$_tags" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_tags="${result:-;}"
|
||||
_tags=$(echo "$_tags" | tr -d '[:space:]')
|
||||
((STEP++))
|
||||
local tags_test="${result:-}"
|
||||
tags_test=$(echo "$tags_test" | tr -d '[:space:]')
|
||||
if validate_tags "$tags_test"; then
|
||||
_tags="$tags_test"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid tag format.\n\nTags can only contain:\n- Letters (a-z, A-Z)\n- Numbers (0-9)\n- Hyphens (-)\n- Underscores (_)\n- Semicolons (;) as separator" 14 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -2044,9 +2474,14 @@ advanced_settings() {
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nSet container timezone.\n\nExamples: Europe/Berlin, America/New_York, Asia/Tokyo\n\nHost timezone: ${_host_timezone:-unknown}\n\nLeave empty to inherit from host." 16 62 "$_ct_timezone" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
_ct_timezone="$result"
|
||||
[[ "${_ct_timezone:-}" == Etc/* ]] && _ct_timezone="host" # pct doesn't accept Etc/* zones
|
||||
((STEP++))
|
||||
local tz_test="$result"
|
||||
[[ "${tz_test:-}" == Etc/* ]] && tz_test="host" # pct doesn't accept Etc/* zones
|
||||
if validate_timezone "$tz_test"; then
|
||||
_ct_timezone="$tz_test"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid timezone: '$result'\n\nTimezone must exist in /usr/share/zoneinfo/\n\nExamples:\n- Europe/Berlin\n- America/New_York\n- Asia/Tokyo\n- UTC" 14 58
|
||||
fi
|
||||
else
|
||||
((STEP--))
|
||||
fi
|
||||
@@ -2843,6 +3278,7 @@ start() {
|
||||
elif [ ! -z ${PHS_SILENT+x} ] && [[ "${PHS_SILENT}" == "1" ]]; then
|
||||
VERBOSE="no"
|
||||
set_std_mode
|
||||
ensure_profile_loaded
|
||||
update_script
|
||||
cleanup_lxc
|
||||
else
|
||||
@@ -2868,6 +3304,7 @@ start() {
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
ensure_profile_loaded
|
||||
update_script
|
||||
cleanup_lxc
|
||||
fi
|
||||
@@ -4306,50 +4743,88 @@ create_lxc_container() {
|
||||
-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}"
|
||||
fi
|
||||
|
||||
# Lock by template file (avoid concurrent downloads/creates)
|
||||
# Lock by template file (avoid concurrent template downloads/validation)
|
||||
lockfile="/tmp/template.${TEMPLATE}.lock"
|
||||
|
||||
# Cleanup stale lock files (older than 1 hour - likely from crashed processes)
|
||||
if [[ -f "$lockfile" ]]; then
|
||||
local lock_age=$(($(date +%s) - $(stat -c %Y "$lockfile" 2>/dev/null || echo 0)))
|
||||
if [[ $lock_age -gt 3600 ]]; then
|
||||
msg_warn "Removing stale template lock file (age: ${lock_age}s)"
|
||||
rm -f "$lockfile"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec 9>"$lockfile" || {
|
||||
msg_error "Failed to create lock file '$lockfile'."
|
||||
exit 200
|
||||
}
|
||||
flock -w 60 9 || {
|
||||
msg_error "Timeout while waiting for template lock."
|
||||
exit 211
|
||||
}
|
||||
|
||||
# Retry logic for template lock (another container creation may be running)
|
||||
local lock_attempts=0
|
||||
local max_lock_attempts=10
|
||||
local lock_wait_time=30
|
||||
|
||||
while ! flock -w "$lock_wait_time" 9; do
|
||||
lock_attempts=$((lock_attempts + 1))
|
||||
if [[ $lock_attempts -ge $max_lock_attempts ]]; then
|
||||
msg_error "Timeout while waiting for template lock after ${max_lock_attempts} attempts."
|
||||
msg_custom "💡" "${YW}" "Another container creation may be stuck. Check running processes or remove: $lockfile"
|
||||
exit 211
|
||||
fi
|
||||
msg_custom "⏳" "${YW}" "Another container is being created with this template. Waiting... (attempt ${lock_attempts}/${max_lock_attempts})"
|
||||
done
|
||||
|
||||
LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log"
|
||||
|
||||
# Validate template before pct create (while holding lock)
|
||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH" 2>/dev/null || echo 0)" -lt 1000000 ]]; then
|
||||
msg_info "Template file missing or too small – downloading"
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1
|
||||
msg_ok "Template downloaded"
|
||||
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
|
||||
if [[ -n "$ONLINE_TEMPLATE" ]]; then
|
||||
msg_info "Template appears corrupted – re-downloading"
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1
|
||||
msg_ok "Template re-downloaded"
|
||||
else
|
||||
msg_warn "Template appears corrupted, but no online version exists. Skipping re-download."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Release lock after template validation - pct create has its own internal locking
|
||||
exec 9>&-
|
||||
|
||||
msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} $PCT_OPTIONS"
|
||||
msg_debug "Logfile: $LOGFILE"
|
||||
|
||||
# First attempt (PCT_OPTIONS is a multi-line string, use it directly)
|
||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" $PCT_OPTIONS >"$LOGFILE" 2>&1; then
|
||||
msg_debug "Container creation failed on ${TEMPLATE_STORAGE}. Validating template..."
|
||||
msg_debug "Container creation failed on ${TEMPLATE_STORAGE}. Checking error..."
|
||||
|
||||
# Validate template file
|
||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||
msg_warn "Template file too small or missing – re-downloading."
|
||||
# Check if template issue - retry with fresh download
|
||||
if grep -qiE 'unable to open|corrupt|invalid' "$LOGFILE"; then
|
||||
msg_info "Template may be corrupted – re-downloading"
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
||||
elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
|
||||
if [[ -n "$ONLINE_TEMPLATE" ]]; then
|
||||
msg_warn "Template appears corrupted – re-downloading."
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
|
||||
else
|
||||
msg_warn "Template appears corrupted, but no online version exists. Skipping re-download."
|
||||
fi
|
||||
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1
|
||||
msg_ok "Template re-downloaded"
|
||||
fi
|
||||
|
||||
# Retry after repair
|
||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" $PCT_OPTIONS >>"$LOGFILE" 2>&1; then
|
||||
# Fallback to local storage if not already on local
|
||||
if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
|
||||
msg_info "Retrying container creation with fallback to local storage..."
|
||||
msg_info "Retrying container creation with fallback to local storage"
|
||||
LOCAL_TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
|
||||
if [[ ! -f "$LOCAL_TEMPLATE_PATH" ]]; then
|
||||
msg_info "Downloading template to local..."
|
||||
msg_ok "Trying local storage fallback"
|
||||
msg_info "Downloading template to local"
|
||||
pveam download local "$TEMPLATE" >/dev/null 2>&1
|
||||
msg_ok "Template downloaded to local"
|
||||
else
|
||||
msg_ok "Trying local storage fallback"
|
||||
fi
|
||||
if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" $PCT_OPTIONS >>"$LOGFILE" 2>&1; then
|
||||
# Local fallback also failed - check for LXC stack version issue
|
||||
|
||||
@@ -38,8 +38,6 @@ load_functions() {
|
||||
icons
|
||||
default_vars
|
||||
set_std_mode
|
||||
# Note: get_lxc_ip() is NOT called here automatically
|
||||
# Call it explicitly when you need LOCAL_IP variable
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -129,6 +127,34 @@ icons() {
|
||||
HOURGLASS="${TAB}⏳${TAB}"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ensure_profile_loaded()
|
||||
#
|
||||
# - Sources /etc/profile.d/*.sh scripts if not already loaded
|
||||
# - Fixes PATH issues when running via pct enter/exec (non-login shells)
|
||||
# - Safe to call multiple times (uses guard variable)
|
||||
# - Should be called in update_script() or any script running inside LXC
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_profile_loaded() {
|
||||
# Skip if already loaded or running on Proxmox host
|
||||
[[ -n "${_PROFILE_LOADED:-}" ]] && return
|
||||
command -v pveversion &>/dev/null && return
|
||||
|
||||
# Source all profile.d scripts to ensure PATH is complete
|
||||
if [[ -d /etc/profile.d ]]; then
|
||||
for script in /etc/profile.d/*.sh; do
|
||||
[[ -r "$script" ]] && source "$script"
|
||||
done
|
||||
fi
|
||||
|
||||
# Also ensure /usr/local/bin is in PATH (common install location)
|
||||
if [[ ":$PATH:" != *":/usr/local/bin:"* ]]; then
|
||||
export PATH="/usr/local/bin:$PATH"
|
||||
fi
|
||||
|
||||
export _PROFILE_LOADED=1
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# default_vars()
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user