diff --git a/api/go.mod b/api/go.mod
index 9a800e283..044bc8428 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -1,6 +1,6 @@
module proxmox-api
-go 1.23.2
+go 1.24.0
require (
github.com/gorilla/mux v1.8.1
@@ -17,7 +17,7 @@ require (
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
- golang.org/x/crypto v0.35.0 // indirect
- golang.org/x/sync v0.11.0 // indirect
- golang.org/x/text v0.22.0 // indirect
+ golang.org/x/crypto v0.45.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
+ golang.org/x/text v0.31.0 // indirect
)
diff --git a/api/go.sum b/api/go.sum
index f0a92be40..cb111bdb8 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -27,16 +27,16 @@ go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793Sqyh
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
-golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
-golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -48,8 +48,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
-golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
diff --git a/ct/asterisk.sh b/ct/asterisk.sh
deleted file mode 100644
index 02f2506cb..000000000
--- a/ct/asterisk.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: michelroegl-brunner
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://asterisk.org/
-
-APP="Asterisk"
-var_tags="${var_tags:-telephone;pbx}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-4}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- msg_error "No Update function provided for ${APP} LXC"
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
diff --git a/ct/kanba.sh b/ct/deferred/kanba.sh
similarity index 100%
rename from ct/kanba.sh
rename to ct/deferred/kanba.sh
diff --git a/ct/domain-locker.sh b/ct/domain-locker.sh
deleted file mode 100644
index f6054664d..000000000
--- a/ct/domain-locker.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: CrazyWolf13
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/Lissy93/domain-locker
-
-APP="Domain-Locker"
-var_tags="${var_tags:-Monitoring}"
-var_cpu="${var_cpu:-4}"
-var_ram="${var_ram:-10240}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/domain-locker ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "domain-locker" "Lissy93/domain-locker"; then
- msg_info "Stopping Service"
- systemctl stop domain-locker
- msg_info "Service stopped"
-
- PG_VERSION="17" setup_postgresql
- setup_nodejs
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "domain-locker" "Lissy93/domain-locker"
-
- msg_info "Installing Modules (patience)"
- cd /opt/domain-locker
- $STD npm install
- msg_ok "Installed Modules"
-
- msg_info "Building Domain-Locker (a lot of patience)"
- npm install
- set -a
- source /opt/domain-locker.env
- set +a
- $STD npm run build
- msg_info "Built Domain-Locker"
-
- msg_info "Restarting Services"
- systemctl start domain-locker
- msg_ok "Restarted Services"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/freepbx.sh b/ct/freepbx.sh
index 0552674bf..fd2395c91 100644
--- a/ct/freepbx.sh
+++ b/ct/freepbx.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-source <(curl -s https://raw.githubusercontent.com/vsc55/community-scripts-ProxmoxVED/refs/heads/freepbx/misc/build.func)
+source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/refs/heads/freepbx/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Arian Nasr (arian-nasr)
# Updated by: Javier Pastor (vsc55)
diff --git a/ct/headers/domain-monitor b/ct/headers/domain-monitor
deleted file mode 100644
index 09b4943e8..000000000
--- a/ct/headers/domain-monitor
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ _ __ ___ _ __
- / __ \____ ____ ___ ____ _(_)___ / |/ /___ ____ (_) /_____ _____
- / / / / __ \/ __ `__ \/ __ `/ / __ \______/ /|_/ / __ \/ __ \/ / __/ __ \/ ___/
- / /_/ / /_/ / / / / / / /_/ / / / / /_____/ / / / /_/ / / / / / /_/ /_/ / /
-/_____/\____/_/ /_/ /_/\__,_/_/_/ /_/ /_/ /_/\____/_/ /_/_/\__/\____/_/
-
diff --git a/ct/headers/miniflux b/ct/headers/miniflux
deleted file mode 100644
index cb3195ae2..000000000
--- a/ct/headers/miniflux
+++ /dev/null
@@ -1,6 +0,0 @@
- __ ____ _ ______
- / |/ (_)___ (_) __/ /_ ___ __
- / /|_/ / / __ \/ / /_/ / / / / |/_/
- / / / / / / / / / __/ / /_/ /> <
-/_/ /_/_/_/ /_/_/_/ /_/\__,_/_/|_|
-
diff --git a/ct/headers/netvisor b/ct/headers/netvisor
deleted file mode 100644
index 034b19e53..000000000
--- a/ct/headers/netvisor
+++ /dev/null
@@ -1,6 +0,0 @@
- _ __ __ _ ___
- / | / /__ / /| | / (_)________ _____
- / |/ / _ \/ __/ | / / / ___/ __ \/ ___/
- / /| / __/ /_ | |/ / (__ ) /_/ / /
-/_/ |_/\___/\__/ |___/_/____/\____/_/
-
diff --git a/ct/headers/passbolt b/ct/headers/passbolt
new file mode 100644
index 000000000..91f0ab71d
--- /dev/null
+++ b/ct/headers/passbolt
@@ -0,0 +1,6 @@
+ ____ __ ____
+ / __ \____ ___________/ /_ ____ / / /_
+ / /_/ / __ `/ ___/ ___/ __ \/ __ \/ / __/
+ / ____/ /_/ (__ |__ ) /_/ / /_/ / / /_
+/_/ \__,_/____/____/_.___/\____/_/\__/
+
diff --git a/ct/headers/splunk-enterprise b/ct/headers/splunk-enterprise
deleted file mode 100644
index f219afef0..000000000
--- a/ct/headers/splunk-enterprise
+++ /dev/null
@@ -1,6 +0,0 @@
- _____ __ __ ______ __ _
- / ___/____ / /_ ______ / /__ / ____/___ / /____ _________ _____(_)_______
- \__ \/ __ \/ / / / / __ \/ //_/_____/ __/ / __ \/ __/ _ \/ ___/ __ \/ ___/ / ___/ _ \
- ___/ / /_/ / / /_/ / / / / ,< /_____/ /___/ / / / /_/ __/ / / /_/ / / / (__ ) __/
-/____/ .___/_/\__,_/_/ /_/_/|_| /_____/_/ /_/\__/\___/_/ / .___/_/ /_/____/\___/
- /_/ /_/
diff --git a/ct/headers/upgopher b/ct/headers/upgopher
new file mode 100644
index 000000000..e1126d09c
--- /dev/null
+++ b/ct/headers/upgopher
@@ -0,0 +1,6 @@
+ __ __ __
+ / / / /___ ____ _____ ____ / /_ ___ _____
+ / / / / __ \/ __ `/ __ \/ __ \/ __ \/ _ \/ ___/
+/ /_/ / /_/ / /_/ / /_/ / /_/ / / / / __/ /
+\____/ .___/\__, /\____/ .___/_/ /_/\___/_/
+ /_/ /____/ /_/
diff --git a/ct/joplin-server.sh b/ct/joplin-server.sh
new file mode 100644
index 000000000..d7824f8ba
--- /dev/null
+++ b/ct/joplin-server.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: Slaviša Arežina (tremor021)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://joplinapp.org/
+
+APP="Joplin-Server"
+var_tags="${var_tags:-notes}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-20}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/joplin-server ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "joplin-server" "laurent22/joplin"; then
+ msg_info "Stopping Services"
+ systemctl stop joplin-server
+ msg_ok "Stopped Services"
+
+ fetch_and_deploy_gh_release "joplin-server" "laurent22/joplin" "tarball" "latest"
+
+ msg_info "Updating Joplin-Server"
+ cd /opt/joplin-server
+ sed -i "/onenote-converter/d" packages/lib/package.json
+ $STD yarn config set --home enableTelemetry 0
+ export BUILD_SEQUENCIAL=1
+ $STD yarn install --inline-builds
+ msg_ok "Updated Joplin-Server"
+
+ msg_info "Starting Services"
+ systemctl start joplin-server
+ msg_ok "Started Services"
+ msg_ok "Updated Successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:22300${CL}"
diff --git a/ct/librenms.sh b/ct/librenms.sh
deleted file mode 100644
index 5df919b12..000000000
--- a/ct/librenms.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: michelroegl-brunner
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://librenms.org
-
-APP="Librenms"
-var_tags="${var_tags:-monitoring}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-4}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [ ! -d /opt/librenms ]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- msg_info "Updating ${APP} Installation"
- su librenms
- cd /opt/librenms
- ./daily.sh
- msg_ok "Updated ${APP} Installation"
-
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/mealie.sh b/ct/mealie.sh
new file mode 100644
index 000000000..3829845d0
--- /dev/null
+++ b/ct/mealie.sh
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://mealie.io
+
+APP="Mealie"
+var_tags="${var_tags:-recipes}"
+var_cpu="${var_cpu:-5}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-10}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -d /opt/mealie ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ if check_for_gh_release "mealie" "mealie-recipes/mealie"; then
+ PYTHON_VERSION="3.12" setup_uv
+ NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs
+
+ msg_info "Stopping Service"
+ systemctl stop mealie
+ msg_ok "Stopped Service"
+
+ msg_info "Backing up configuration"
+ mkdir -p /opt/mealie_bak
+ cp -f /opt/mealie/mealie.env /opt/mealie_bak/mealie.env.bak
+ cp -f /opt/mealie/start.sh /opt/mealie_bak/start.sh.bak
+ msg_ok "Backup completed"
+
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "latest" "/opt/mealie"
+
+ msg_info "Rebuilding Frontend"
+ export NUXT_TELEMETRY_DISABLED=1
+ cd /opt/mealie/frontend
+ $STD yarn install --prefer-offline --frozen-lockfile --non-interactive --production=false --network-timeout 1000000
+ $STD yarn generate
+ cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
+ msg_ok "Frontend rebuilt"
+
+ msg_info "Updating Python Dependencies"
+ cd /opt/mealie
+ $STD uv sync --frozen --extra pgsql
+ msg_ok "Dependencies updated"
+
+ msg_info "Restoring configuration"
+ grep -q "^SECRET=" /opt/mealie_bak/mealie.env.bak || echo "SECRET=$(openssl rand -hex 32)" >>/opt/mealie_bak/mealie.env.bak
+ grep -q "^MEALIE_HOME=" /opt/mealie_bak/mealie.env.bak || echo "MEALIE_HOME=/opt/mealie" >>/opt/mealie_bak/mealie.env.bak
+ grep -q "^NLTK_DATA=" /opt/mealie_bak/mealie.env.bak || echo "NLTK_DATA=/nltk_data" >>/opt/mealie_bak/mealie.env.bak
+
+ mv -f /opt/mealie_bak/mealie.env.bak /opt/mealie/mealie.env
+ mv -f /opt/mealie_bak/start.sh.bak /opt/mealie/start.sh
+ chmod +x /opt/mealie/start.sh
+ sed -i 's|exec .*|source /opt/mealie/.venv/bin/activate\nexec uv run mealie|' /opt/mealie/start.sh
+ msg_ok "Configuration restored"
+
+ msg_info "Starting Service"
+ systemctl start mealie
+ msg_ok "Started Service"
+ msg_ok "Updated successfully"
+ fi
+
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9000${CL}"
diff --git a/ct/omada.sh b/ct/omada.sh
deleted file mode 100644
index 576797b71..000000000
--- a/ct/omada.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.tp-link.com/us/support/download/omada-software-controller/
-
-APP="Omada"
-var_tags="${var_tags:-tp-link;controller}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-3072}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/tplink ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- msg_info "Updating MongoDB"
- if lscpu | grep -q 'avx'; then
- MONGO_VERSION="8.0" setup_mongodb
- else
- msg_warn "No AVX detected: Using older MongoDB 4.4"
- MONGO_VERSION="4.4" setup_mongodb
- fi
-
- msg_info "Checking if right Azul Zulu Java is installed"
- java_version=$(java -version 2>&1 | awk -F[\"_] '/version/ {print $2}')
- if [[ "$java_version" =~ ^1\.8\.* ]]; then
- $STD apt remove --purge -y zulu8-jdk
- $STD apt -y install zulu21-jre-headless
- msg_ok "Updated Azul Zulu Java to 21"
- else
- msg_ok "Azul Zulu Java 21 already installed"
- fi
-
- msg_info "Updating Omada Controller"
- OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" |
- grep -o 'https://static\.tp-link\.com/upload/software/[^"]*linux_x64[^"]*\.deb' |
- head -n1)
- OMADA_PKG=$(basename "$OMADA_URL")
- if [ -z "$OMADA_PKG" ]; then
- msg_error "Could not retrieve Omada package – server may be down."
- exit
- fi
- curl -fsSL "$OMADA_URL" -o "$OMADA_PKG"
- export DEBIAN_FRONTEND=noninteractive
- $STD dpkg -i "$OMADA_PKG"
- rm -f "$OMADA_PKG"
- msg_ok "Updated successfully!"
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8043${CL}"
diff --git a/ct/passbolt.sh b/ct/passbolt.sh
deleted file mode 100644
index caf0696ba..000000000
--- a/ct/passbolt.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: Slaviša Arežina (tremor021)
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://www.passbolt.com/
-
-APP="Passbolt"
-var_tags="${var_tags:-auth}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-2}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /var ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- msg_info "Updating $APP LXC"
- $STD apt update
- $STD apt upgrade -y
- msg_ok "Updated $APP LXC"
- cleanup_lxc
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}https://${IP}${CL}"
diff --git a/ct/upgopher.sh b/ct/upgopher.sh
deleted file mode 100644
index cd7b4d69a..000000000
--- a/ct/upgopher.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: Eduard González (wanetty)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/wanetty/upgopher
-
-APP="Upgopher"
-var_tags="${var_tags:-file-sharing}"
-var_cpu="${var_cpu:-1}"
-var_ram="${var_ram:-512}"
-var_disk="${var_disk:-4}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/upgopher ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "upgopher" "wanetty/upgopher"; then
- msg_info "Stopping Service"
- systemctl stop upgopher
- msg_ok "Stopped Service"
-
- fetch_and_deploy_gh_release "upgopher" "wanetty/upgopher" "prebuild" "latest" "/opt/upgopher" "upgopher_*_linux_amd64.tar.gz"
- chmod +x /opt/upgopher/upgopher
-
- msg_info "Starting Service"
- systemctl start upgopher
- msg_ok "Started Service"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9090${CL}"
diff --git a/frontend/public/json/domain-locker.json b/frontend/public/json/domain-locker.json
deleted file mode 100644
index 9a9260903..000000000
--- a/frontend/public/json/domain-locker.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "Domain Locker",
- "slug": "domain-locker",
- "categories": [
- 9
- ],
- "date_created": "2025-11-10",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 3000,
- "documentation": "https://domain-locker.com/about",
- "config_path": "/opt/domain-locker.env",
- "website": "https://github.com/Lissy93/domain-locker",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/domain-locker.webp",
- "description": "The all-in-one tool, for keeping track of your domain name portfolio. Got domain names? Get Domain Locker! ",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/domain-locker.sh",
- "resources": {
- "cpu": 2,
- "ram": 4096,
- "hdd": 8,
- "os": "Debian",
- "version": "13"
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": [
- {
- "text": "Show DB credentials: `cat ~/Domain-Locker.creds`",
- "type": "info"
- },
- {
- "text": "Domain-locker takes quite some time to build and a lot of ressources, RAM and Cores can be lowered after install.",
- "type": "info"
- }
- ]
-}
diff --git a/frontend/public/json/ente.json b/frontend/public/json/ente.json
new file mode 100644
index 000000000..794580914
--- /dev/null
+++ b/frontend/public/json/ente.json
@@ -0,0 +1,48 @@
+{
+ "name": "Ente",
+ "slug": "ente",
+ "categories": [
+ 20
+ ],
+ "date_created": "2025-11-22",
+ "type": "ct",
+ "updateable": false,
+ "privileged": false,
+ "config_path": "/opt",
+ "interface_port": 3000,
+ "documentation": "https://github.com/ente-io/ente",
+ "website": "https://ente.io/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/ente-photos.svg",
+ "description": "Ente is a service that provides a fully open source, end-to-end encrypted platform for you to store your data in the cloud without needing to trust the service provider. On top of this platform, we have built two apps so far: Ente Photos (an alternative to Apple and Google Photos) and Ente Auth (a 2FA alternative to the deprecated Authy).",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/ente.sh",
+ "resources": {
+ "cpu": 4,
+ "ram": 4096,
+ "hdd": 10,
+ "os": "debian",
+ "version": "12"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "Please use `journalctl -u ente-museum.service -n 10` to read logs for the signup verification code",
+ "type": "info"
+ },
+ {
+ "text": "If you want to use the Ente CLI to add/whitelist admins, please follow the instructions at https://ente.io/help/self-hosting/administration/cli",
+ "type": "info"
+ },
+ {
+ "text": "To see Museium config: `cat /opt/ente/server/museum.yaml`",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/librenms.json b/frontend/public/json/librenms.json
deleted file mode 100644
index 39f738c12..000000000
--- a/frontend/public/json/librenms.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "LibreNMS",
- "slug": "librenms",
- "categories": [
- 9
- ],
- "date_created": "2025-03-24",
- "type": "ct",
- "updateable": false,
- "privileged": false,
- "interface_port": 80,
- "documentation": "https://docs.librenms.org/",
- "website": "https://librenms.org/",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/librenms.webp",
- "config_path": "/opt/librenms/config.php and /opt/librenms/.env",
- "description": "LibreNMS is an open-source, community-driven network monitoring system that provides automatic discovery, alerting, and performance tracking for network devices. It supports a wide range of hardware and integrates with various notification and logging platforms.",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/librenms.sh",
- "resources": {
- "cpu": 2,
- "ram": 2048,
- "hdd": 4,
- "os": "Debian",
- "version": "12"
- }
- }
- ],
- "default_credentials": {
- "username": "admin",
- "password": "admin"
- },
- "notes": []
-}
diff --git a/frontend/public/json/passbolt.json b/frontend/public/json/passbolt.json
deleted file mode 100644
index 09359e49d..000000000
--- a/frontend/public/json/passbolt.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "Passbolt",
- "slug": "passbolt",
- "categories": [
- 6
- ],
- "date_created": "2025-09-04",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 443,
- "documentation": "https://www.passbolt.com/docs/",
- "config_path": "/etc/passbolt/passbolt.php",
- "website": "https://www.passbolt.com/",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/passbolt.webp",
- "description": "Passbolt is a hybrid credential platform. It is built-first for modern IT teams, yet simple enough for everyone. A sovereign, battle-tested solution that delivers for a team of 5, or an organisation of 5000.",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/passbolt.sh",
- "resources": {
- "cpu": 2,
- "ram": 2048,
- "hdd": 2,
- "os": "Debian",
- "version": "13"
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": [
- {
- "text": "Type `cat ~/.Passbolt.creds` to see MariaDB database credentials. You will need those to setup Passbolt.",
- "type": "info"
- },
- {
- "text": "The application uses self-signed certificates. You can also use Let's Encrypt to get a valid certificate for your domain. Please read the documentation for more information.",
- "type": "info"
- }
- ]
-}
diff --git a/frontend/public/json/qbittorrent-exporter.json b/frontend/public/json/qbittorrent-exporter.json
new file mode 100644
index 000000000..0c4ba9c38
--- /dev/null
+++ b/frontend/public/json/qbittorrent-exporter.json
@@ -0,0 +1,46 @@
+{
+ "name": "qbittorrent Exporter",
+ "slug": "qbittorrent-exporter",
+ "categories": [
+ 9
+ ],
+ "date_created": "2025-11-21",
+ "type": "addon",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 8090,
+ "documentation": "https://github.com/martabal/qbittorrent-exporter",
+ "website": "https://github.com/martabal/qbittorrent-exporter",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/qbittorrent.webp",
+ "config_path": "/opt/qbittorrent-exporter.env",
+ "description": "A fast and lightweight prometheus exporter for qBittorrent ",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "tools/addon/qbittorrent-exporter.sh",
+ "resources": {
+ "cpu": null,
+ "ram": null,
+ "hdd": null,
+ "os": null,
+ "version": null
+ }
+ },
+ {
+ "type": "alpine",
+ "script": "tools/addon/qbittorrent-exporter.sh",
+ "resources": {
+ "cpu": null,
+ "ram": null,
+ "hdd": null,
+ "os": null,
+ "version": null
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/upgopher.json b/frontend/public/json/upgopher.json
deleted file mode 100644
index 3e54643a0..000000000
--- a/frontend/public/json/upgopher.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "name": "Upgopher",
- "slug": "upgopher",
- "categories": [
- 11
- ],
- "date_created": "2025-10-31",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 9090,
- "documentation": "https://github.com/wanetty/upgopher#readme",
- "config_path": "",
- "website": "https://github.com/wanetty/upgopher",
- "logo": "https://raw.githubusercontent.com/wanetty/upgopher/main/static/logopher.webp",
- "description": "A simple Go web server for file upload, download, and browsing. Cross-platform alternative to Python-based file servers with no library dependencies. Features file upload via web interface, directory navigation, URL copying to clipboard, optional basic authentication, HTTPS support, and hidden files toggle.",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/upgopher.sh",
- "resources": {
- "cpu": 1,
- "ram": 512,
- "hdd": 4,
- "os": "Debian",
- "version": "13"
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": [
- {
- "text": "Default: HTTP on port 9090, no authentication, uploads dir: /opt/upgopher/uploads",
- "type": "info"
- },
- {
- "text": "To customize: edit /etc/systemd/system/upgopher.service and modify ExecStart line. Available flags: -user -pass (authentication), -ssl (HTTPS with self-signed cert), -port (custom port), -dir (upload directory), -disable-hidden-files (hide hidden files)",
- "type": "info"
- },
- {
- "text": "Example with auth: ExecStart=/opt/upgopher/upgopher -port 9090 -dir /opt/upgopher/uploads -user admin -pass mysecret",
- "type": "info"
- },
- {
- "text": "After editing service file: systemctl daemon-reload && systemctl restart upgopher",
- "type": "info"
- }
- ]
-}
diff --git a/install/asterisk-install.sh b/install/asterisk-install.sh
deleted file mode 100644
index 202c12e10..000000000
--- a/install/asterisk-install.sh
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: michelroegl-brunner
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://asterisk.org
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-ASTERISK_VERSIONS_URL="https://www.asterisk.org/downloads/asterisk/all-asterisk-versions/"
-html=$(curl -fsSL "$ASTERISK_VERSIONS_URL")
-
-LTS_VERSION=""
-for major in 20 22 24 26; do
- block=$(echo "$html" | awk "/Asterisk $major - LTS/,//" || true)
- ver=$(echo "$block" | grep -oE 'Download Latest - [0-9]+\.[0-9]+(\.[0-9]+)?' | head -n1 | sed -E 's/.* - //' || true)
- if [ -n "$ver" ]; then
- LTS_VERSION="$LTS_VERSION $ver"
- fi
- unset ver block
-done
-LTS_VERSION=$(echo "$LTS_VERSION" | xargs | tr ' ' '\n' | sort -V | tail -n1)
-
-STD_VERSION=""
-for major in 21 23 25 27; do
- block=$(echo "$html" | grep -A 20 "Asterisk $major" | head -n 20 || true)
- ver=$(echo "$block" | grep -oE 'Download (Latest - )?'"$major"'\.[0-9]+\.[0-9]+' | head -n1 | sed -E 's/Download (Latest - )?//' || true)
- if [ -n "$ver" ]; then
- STD_VERSION="$STD_VERSION $ver"
- fi
- unset ver block
-done
-STD_VERSION=$(echo "$STD_VERSION" | xargs | tr ' ' '\n' | sort -V | tail -n1)
-
-cert_block=$(echo "$html" | awk '/Certified Asterisk/,//')
-CERT_VERSION=$(echo "$cert_block" | grep -oE 'Download Latest - [0-9]+\.[0-9]+-cert[0-9]+' | head -n1 | sed -E 's/.* - //' || true)
-
-cat </opt/cronmaster/.env
+NODE_ENV=production
+APP_URL=
+LOCALE=
+HOME=
+AUTH_PASSWORD=${AUTH_PASS}
+PORT=3000
+HOSTNAME="0.0.0.0"
+NEXT_TELEMETRY_DISABLED=1
+EOF
+{
+ echo "CronMaster Credentials:"
+ echo ""
+ echo "Password: $AUTH_PASS"
+}>>~/cronmaster.creds
+msg_ok "Setup CronMaster"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/cronmaster.service
+[Unit]
+Description=CronMaster Service
+After=network.target
+
+[Service]
+EnvironmentFile=/opt/cronmaster/.env
+WorkingDirectory=/opt/cronmaster
+ExecStart=/usr/bin/yarn start
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl start --now -q cronmaster
+msg_info "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/domain-locker-install.sh b/install/domain-locker-install.sh
deleted file mode 100644
index 17dcd1a47..000000000
--- a/install/domain-locker-install.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: CrazyWolf13
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://github.com/CrazyWolf13/domain-locker
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="domainlocker" PG_DB_USER="domainlocker" setup_postgresql_db
-NODE_VERSION="22" setup_nodejs
-
-fetch_and_deploy_gh_release "domain-locker" "Lissy93/domain-locker"
-
-msg_info "Installing Modules (patience)"
-cd /opt/domain-locker
-$STD npm install
-msg_ok "Installed Modules"
-
-msg_info "Building Domain-Locker (a lot of patience)"
-cat </opt/domain-locker.env
-# Database connection
-DL_PG_HOST=localhost
-DL_PG_PORT=5432
-DL_PG_USER=$PG_DB_USER
-DL_PG_PASSWORD=$PG_DB_PASS
-DL_PG_NAME=$PG_DB_NAME
-
-# Build + Runtime
-DL_ENV_TYPE=selfHosted
-NITRO_PRESET=node_server
-NODE_ENV=production
-EOF
-set -a
-source /opt/domain-locker.env
-set +a
-$STD npm run build
-msg_info "Built Domain-Locker"
-
-msg_info "Building Database schema"
-export PGPASSWORD="$DL_PG_PASSWORD"
-$STD psql -h "$DL_PG_HOST" -p "$DL_PG_PORT" -U "$DL_PG_USER" -d "$DL_PG_NAME" -f "/opt/domain-locker/db/schema.sql"
-msg_ok "Built Database schema"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/domain-locker.service
-[Unit]
-Description=Domain-Locker Service
-After=network.target
-
-[Service]
-EnvironmentFile=/opt/domain-locker.env
-WorkingDirectory=/opt/domain-locker
-ExecStart=/opt/domain-locker/start.sh
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl start --now -q domain-locker
-msg_info "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/ente-install.sh b/install/ente-install.sh
index c0fe3697f..9a4fbdee6 100644
--- a/install/ente-install.sh
+++ b/install/ente-install.sh
@@ -28,8 +28,22 @@ PG_VERSION="17" setup_postgresql
setup_go
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
ENTE_CLI_VERSION=$(curl -s https://api.github.com/repos/ente-io/ente/releases | jq -r '[.[] | select(.tag_name | startswith("cli-v"))][0].tag_name')
-fetch_and_deploy_gh_release "ente" "ente-io/ente" "tarball" "latest" "/opt/ente"
-fetch_and_deploy_gh_release "ente" "ente-io/ente" "tarball" "$ENTE_CLI_VERSION" "/usr/local/bin/ente" "ente-cli-$ENTE_CLI_VERSION-linux-amd64.tar.gz"
+fetch_and_deploy_gh_release "ente-server" "ente-io/ente" "tarball" "latest" "/opt/ente"
+fetch_and_deploy_gh_release "ente-cli" "ente-io/ente" "prebuild" "$ENTE_CLI_VERSION" "/usr/local/bin" "ente-$ENTE_CLI_VERSION-linux-amd64.tar.gz"
+
+$STD mkdir -p /opt/ente/cli
+msg_info "Configuring Ente CLI"
+cat <>~/.bashrc
+export ENTE_CLI_SECRETS_PATH=/opt/ente/cli/secrets.txt
+export PATH="/usr/local/bin:$PATH"
+EOF
+$STD source ~/.bashrc
+$STD mkdir -p ~/.ente
+cat <~/.ente/config.yaml
+endpoint:
+ api: http://localhost:8080
+EOF
+msg_ok "Configured Ente CLI"
msg_info "Setting up PostgreSQL"
DB_NAME="ente_db"
@@ -133,13 +147,37 @@ jwt:
EOF
msg_ok "Created museum.yaml"
+read -r -p "Enter the public URL for Ente backend (e.g., https://api.ente.yourdomain.com or http://192.168.1.100:8080) leave empty to use container IP: " backend_url
+if [[ -z "$backend_url" ]]; then
+ LOCAL_IP=$(hostname -I | awk '{print $1}')
+ ENTE_BACKEND_URL="http://$LOCAL_IP:8080"
+ msg_info "No URL provided"
+ msg_ok "using local IP: $ENTE_BACKEND_URL\n"
+else
+ ENTE_BACKEND_URL="$backend_url"
+ msg_info "URL provided"
+ msg_ok "Using provided URL: $ENTE_BACKEND_URL\n"
+fi
+
+read -r -p "Enter the public URL for Ente albums (e.g., https://albums.ente.yourdomain.com or http://192.168.1.100:3002) leave empty to use container IP: " albums_url
+if [[ -z "$albums_url" ]]; then
+ LOCAL_IP=$(hostname -I | awk '{print $1}')
+ ENTE_ALBUMS_URL="http://$LOCAL_IP:3002"
+ msg_info "No URL provided"
+ msg_ok "using local IP: $ENTE_ALBUMS_URL\n"
+else
+ ENTE_ALBUMS_URL="$albums_url"
+ msg_info "URL provided"
+ msg_ok "Using provided URL: $ENTE_ALBUMS_URL\n"
+fi
+
+export NEXT_PUBLIC_ENTE_ENDPOINT=$ENTE_BACKEND_URL
+export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=$ENTE_ALBUMS_URL
+
msg_info "Building Web Applications"
-# Get container IP address
-CONTAINER_IP=$(hostname -I | awk '{print $1}')
cd /opt/ente/web
+export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
$STD yarn install
-export NEXT_PUBLIC_ENTE_ENDPOINT=http://${CONTAINER_IP}:8080
-export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=http://${CONTAINER_IP}:3002
$STD yarn build
$STD yarn build:accounts
$STD yarn build:auth
@@ -153,12 +191,35 @@ cp -r apps/cast/out /var/www/ente/apps/cast
# Save build configuration for future rebuilds
cat </opt/ente/rebuild-frontend.sh
#!/usr/bin/env bash
-# Rebuild Ente frontend with current IP
-CONTAINER_IP=\$(hostname -I | awk '{print \$1}')
-echo "Building frontend with IP: \$CONTAINER_IP"
+# Rebuild Ente frontend
+# Prompt for backend URL
+read -r -p "Enter the public URL for Ente backend (e.g., https://api.ente.yourdomain.com or http://192.168.1.100:8080) leave empty to use container IP: " backend_url
+if [[ -z "\$backend_url" ]]; then
+ LOCAL_IP=$(hostname -I | awk '{print $1}')
+ ENTE_BACKEND_URL="http://\$LOCAL_IP:8080"
+ echo "No URL provided, using local IP: \$ENTE_BACKEND_URL\n"
+else
+ ENTE_BACKEND_URL="\$backend_url"
+ echo "Using provided URL: \$ENTE_BACKEND_URL\n"
+fi
+
+# Prompt for albums URL
+read -r -p "Enter the public URL for Ente albums (e.g., https://albums.ente.yourdomain.com or http://192.168.1.100:3002) leave empty to use container IP: " albums_url
+if [[ -z "\$albums_url" ]]; then
+ LOCAL_IP=\$(hostname -I | awk '{print $1}')
+ ENTE_ALBUMS_URL="http://\$LOCAL_IP:3002"
+ echo "No URL provided, using local IP: \$ENTE_ALBUMS_URL\n"
+else
+ ENTE_ALBUMS_URL="\$albums_url"
+ echo "Using provided URL: \$ENTE_ALBUMS_URL\n"
+fi
+
+export NEXT_PUBLIC_ENTE_ENDPOINT=\$ENTE_BACKEND_URL
+export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=\$ENTE_ALBUMS_URL
+
+echo "Building Web Applications\n"
+
cd /opt/ente/web
-export NEXT_PUBLIC_ENTE_ENDPOINT=http://\${CONTAINER_IP}:8080
-export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=http://\${CONTAINER_IP}:3002
yarn build
yarn build:accounts
yarn build:auth
@@ -312,8 +373,9 @@ echo -e "━━━━━━━━━━━━━━━━━━━━━━━
echo -e "\n${BL}Access URLs:${CL}"
echo -e " Photos: http://${CONTAINER_IP}:3000"
echo -e " Accounts: http://${CONTAINER_IP}:3001"
+echo -e " Albums: ${ENTE_ALBUMS_URL}"
echo -e " Auth: http://${CONTAINER_IP}:3003"
-echo -e " API: http://${CONTAINER_IP}:8080"
+echo -e " API: ${ENTE_BACKEND_URL}"
echo -e "\n${YW}⚠️ Important Post-Installation Steps:${CL}"
echo -e "\n${BL}1. Create your first account:${CL}"
echo -e " • Open http://${CONTAINER_IP}:3000 in your browser"
diff --git a/install/joplin-server-install.sh b/install/joplin-server-install.sh
new file mode 100644
index 000000000..35d85fbf2
--- /dev/null
+++ b/install/joplin-server-install.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: Slaviša Arežina (tremor021)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://joplinapp.org/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ git \
+ rsync
+msg_ok "Installed Dependencies"
+
+PG_VERSION="17" setup_postgresql
+NODE_VERSION=24 NODE_MODULE="yarn,npm,pm2" setup_nodejs
+mkdir -p /opt/pm2
+export PM2_HOME=/opt/pm2
+$STD pm2 install pm2-logrotate
+$STD pm2 set pm2-logrotate:max_size 100MB
+$STD pm2 set pm2-logrotate:retain 5
+$STD pm2 set pm2-logrotate:compress tr
+
+msg_info "Setting up PostgreSQL Database"
+DB_NAME=joplin
+DB_USER=joplin
+DB_PASS="$(openssl rand -base64 18 | cut -c1-13)"
+$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
+$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
+$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';"
+$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';"
+$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC'"
+{
+ echo "Joplin-Credentials"
+ echo "Joplin Database User: $DB_USER"
+ echo "Joplin Database Password: $DB_PASS"
+ echo "Joplin Database Name: $DB_NAME"
+} >>~/joplin.creds
+msg_ok "Set up PostgreSQL Database"
+
+fetch_and_deploy_gh_release "joplin-server" "laurent22/joplin" "tarball" "latest"
+
+msg_info "Setting up Joplin Server (Patience)"
+LOCAL_IP=$(hostname -I | awk '{print $1}')
+cd /opt/joplin-server
+sed -i "/onenote-converter/d" packages/lib/package.json
+$STD yarn config set --home enableTelemetry 0
+export BUILD_SEQUENCIAL=1
+$STD yarn install --inline-builds
+
+cat </opt/joplin-server/.env
+PM2_HOME=/opt/pm2
+NODE_ENV=production
+APP_BASE_URL=http://$LOCAL_IP:22300
+APP_PORT=22300
+DB_CLIENT=pg
+POSTGRES_PASSWORD=$DB_PASS
+POSTGRES_DATABASE=$DB_NAME
+POSTGRES_USER=$DB_USER
+POSTGRES_PORT=5432
+POSTGRES_HOST=localhost
+EOF
+msg_ok "Setup Joplin Server"
+
+msg_info "Setting up Service"
+cat </etc/systemd/system/joplin-server.service
+[Unit]
+Description=Joplin Server Service
+After=network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/opt/joplin-server/packages/server
+EnvironmentFile=/opt/joplin-server/.env
+ExecStart=/usr/bin/yarn start-prod
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now joplin-server
+msg_ok "Service Setup"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/librenms-install.sh b/install/librenms-install.sh
deleted file mode 100644
index 07079e9ce..000000000
--- a/install/librenms-install.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: michelroegl-brunner
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://github.com/opf/openproject
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y \
- acl \
- fping \
- graphviz \
- imagemagick \
- mtr-tiny \
- nginx \
- nmap \
- rrdtool \
- snmp \
- snmpd \
- whois
-msg_ok "Installed Dependencies"
-
-PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="gmp,mysql,snmp" setup_php
-setup_mariadb
-setup_composer
-PYTHON_VERSION="3.13" setup_uv
-
-msg_info "Installing Python Dependencies"
-$STD apt install -y \
- python3-dotenv \
- python3-pymysql \
- python3-redis \
- python3-setuptools \
- python3-systemd \
- python3-pip
-msg_ok "Installed Python Dependencies"
-
-
-
-MARIADB_DB_NAME="librenms" MARIADB_DB_USER="librenms" MARIADB_DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)" setup_mariadb_db
-
-fetch_and_deploy_gh_release "librenms" "librenms/librenms"
-
-msg_info "Configuring LibreNMS"
-$STD useradd librenms -d /opt/librenms -M -r -s "$(which bash)"
-mkdir -p /opt/librenms/{rrd,logs,bootstrap/cache,storage,html}
-cd /opt/librenms
-APP_KEY=$(openssl rand -base64 40 | tr -dc 'a-zA-Z0-9')
-$STD uv venv .venv
-$STD source .venv/bin/activate
-$STD uv pip install -r requirements.txt
-cat </opt/librenms/.env
-DB_DATABASE=${MARIADB_DB_NAME}
-DB_USERNAME=${MARIADB_DB_USER}
-DB_PASSWORD=${MARIADB_DB_PASS}
-APP_KEY=${APP_KEY}
-EOF
-chown -R librenms:librenms /opt/librenms
-chmod 771 /opt/librenms
-chmod -R ug=rwX /opt/librenms/bootstrap/cache /opt/librenms/storage /opt/librenms/logs /opt/librenms/rrd
-msg_ok "Configured LibreNMS"
-
-msg_info "Configure MariaDB"
-sed -i "/\[mysqld\]/a innodb_file_per_table=1\nlower_case_table_names=0" /etc/mysql/mariadb.conf.d/50-server.cnf
-systemctl enable -q --now mariadb
-msg_ok "Configured MariaDB"
-
-msg_info "Configure PHP-FPM"
-cp /etc/php/8.4/fpm/pool.d/www.conf /etc/php/8.4/fpm/pool.d/librenms.conf
-sed -i "s/\[www\]/\[librenms\]/g" /etc/php/8.4/fpm/pool.d/librenms.conf
-sed -i "s/user = www-data/user = librenms/g" /etc/php/8.4/fpm/pool.d/librenms.conf
-sed -i "s/group = www-data/group = librenms/g" /etc/php/8.4/fpm/pool.d/librenms.conf
-sed -i "s/listen = \/run\/php\/php8.4-fpm.sock/listen = \/run\/php-fpm-librenms.sock/g" /etc/php/8.4/fpm/pool.d/librenms.conf
-msg_ok "Configured PHP-FPM"
-
-msg_info "Configure Nginx"
-IP_ADDR=$(hostname -I | awk '{print $1}')
-cat >/etc/nginx/sites-enabled/librenms <<'EOF'
-server {
- listen 80;
- server_name ${IP_ADDR};
- root /opt/librenms/html;
- index index.php;
-
- charset utf-8;
- gzip on;
- gzip_types text/css application/javascript text/javascript application/x-javascript image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
- location / {
- try_files $uri $uri/ /index.php?$query_string;
- }
- location ~ [^/]\.php(/|$) {
- fastcgi_pass unix:/run/php-fpm-librenms.sock;
- fastcgi_split_path_info ^(.+\.php)(/.+)$;
- include fastcgi.conf;
- }
- location ~ /\.(?!well-known).* {
- deny all;
- }
-}
-EOF
-rm /etc/nginx/sites-enabled/default
-$STD systemctl reload nginx
-systemctl restart php8.4-fpm
-msg_ok "Configured Nginx"
-
-msg_info "Configure Services"
-ln -s /opt/librenms/lnms /usr/bin/lnms
-mkdir -p /etc/bash_completion.d/
-cp /opt/librenms/misc/lnms-completion.bash /etc/bash_completion.d/
-cp /opt/librenms/snmpd.conf.example /etc/snmp/snmpd.conf
-
-$STD su - librenms -s /bin/bash -c "cd /opt/librenms && COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev"
-$STD su - librenms -s /bin/bash -c "cd /opt/librenms && php8.4 artisan migrate --force"
-$STD su - librenms -s /bin/bash -c "cd /opt/librenms && php8.4 artisan key:generate --force"
-$STD su - librenms -s /bin/bash -c "cd /opt/librenms && lnms db:seed --force"
-$STD su - librenms -s /bin/bash -c "cd /opt/librenms && lnms user:add -p admin -r admin admin"
-
-
-RANDOM_STRING=$(openssl rand -base64 16 | tr -dc 'a-zA-Z0-9')
-sed -i "s/RANDOMSTRINGHERE/$RANDOM_STRING/g" /etc/snmp/snmpd.conf
-echo "SNMP Community String: $RANDOM_STRING" >>~/librenms.creds
-curl -qso /usr/bin/distro https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/distro
-chmod +x /usr/bin/distro
-systemctl enable -q --now snmpd
-
-cp /opt/librenms/dist/librenms.cron /etc/cron.d/librenms
-cp /opt/librenms/dist/librenms-scheduler.service /opt/librenms/dist/librenms-scheduler.timer /etc/systemd/system/
-
-systemctl enable -q --now librenms-scheduler.timer
-cp /opt/librenms/misc/librenms.logrotate /etc/logrotate.d/librenms
-msg_ok "Configured Services"
-
-motd_ssh
-customize
-
-msg_info "Cleaning up"
-$STD apt -y autoremove
-$STD apt -y autoclean
-msg_ok "Cleaned"
diff --git a/install/mealie-install.sh b/install/mealie-install.sh
new file mode 100644
index 000000000..8b330fab4
--- /dev/null
+++ b/install/mealie-install.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://mealie.io
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ build-essential \
+ libpq-dev \
+ libwebp-dev \
+ libsasl2-dev \
+ libldap2-dev \
+ libssl-dev
+msg_ok "Installed Dependencies"
+
+PYTHON_VERSION="3.12" setup_uv
+POSTGRES_VERSION="16" setup_postgresql
+NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs
+fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "latest" "/opt/mealie"
+PG_DB_NAME="mealie_db" PG_DB_USER="mealie_user" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
+
+msg_info "Installing Python Dependencies with uv"
+cd /opt/mealie
+$STD uv sync --frozen --extra pgsql
+msg_ok "Installed Python Dependencies"
+
+msg_info "Building Frontend"
+export NUXT_TELEMETRY_DISABLED=1
+cd /opt/mealie/frontend
+$STD yarn install --prefer-offline --frozen-lockfile --non-interactive --production=false --network-timeout 1000000
+$STD yarn generate
+msg_ok "Built Frontend"
+
+msg_info "Copying Built Frontend"
+mkdir -p /opt/mealie/mealie/frontend
+cp -r /opt/mealie/frontend/dist/* /opt/mealie/mealie/frontend/
+msg_ok "Copied Frontend"
+
+msg_info "Downloading NLTK Data"
+mkdir -p /nltk_data/
+cd /opt/mealie
+$STD uv run python -m nltk.downloader -d /nltk_data averaged_perceptron_tagger_eng
+msg_ok "Downloaded NLTK Data"
+
+msg_info "Writing Environment File"
+SECRET=$(openssl rand -hex 32)
+mkdir -p /run/secrets
+cat </opt/mealie/mealie.env
+MEALIE_HOME=/opt/mealie
+NLTK_DATA=/nltk_data
+SECRET=${SECRET}
+
+DB_ENGINE=postgres
+POSTGRES_SERVER=localhost
+POSTGRES_PORT=5432
+POSTGRES_USER=${PG_DB_USER}
+POSTGRES_PASSWORD=${PG_DB_PASS}
+POSTGRES_DB=${PG_DB_NAME}
+
+PRODUCTION=true
+HOST=0.0.0.0
+PORT=9000
+EOF
+msg_ok "Wrote Environment File"
+
+msg_info "Creating Start Script"
+cat <<'EOF' >/opt/mealie/start.sh
+#!/bin/bash
+set -a
+source /opt/mealie/mealie.env
+set +a
+exec uv run mealie
+EOF
+chmod +x /opt/mealie/start.sh
+msg_ok "Created Start Script"
+
+msg_info "Creating Systemd Service"
+cat <<'EOF' >/etc/systemd/system/mealie.service
+[Unit]
+Description=Mealie Recipe Manager
+After=network.target postgresql.service
+Wants=postgresql.service
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/opt/mealie
+ExecStart=/opt/mealie/start.sh
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now mealie
+msg_ok "Created and Started Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/omada-install.sh b/install/omada-install.sh
deleted file mode 100644
index 7ffc14fb7..000000000
--- a/install/omada-install.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.tp-link.com/us/support/download/omada-software-controller/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y jsvc
-msg_ok "Installed Dependencies"
-
-if lscpu | grep -q 'avx'; then
- MONGO_VERSION="8.0" setup_mongodb
-else
- MONGO_VERSION="4.4" setup_mongodb
-fi
-
-JAVA_VERSION="21" setup_java
-
-# if ! dpkg -l | grep -q 'libssl1.1'; then
-# msg_info "Installing libssl (if needed)"
-# curl -fsSL "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u4_amd64.deb" -o "/tmp/libssl.deb"
-# $STD dpkg -i /tmp/libssl.deb
-# rm -f /tmp/libssl.deb
-# msg_ok "Installed libssl1.1"
-# fi
-
-msg_info "Installing Omada Controller"
-OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" |
- grep -o 'https://static\.tp-link\.com/upload/software/[^"]*linux_x64[^"]*\.deb' |
- head -n1)
-OMADA_PKG=$(basename "$OMADA_URL")
-curl -fsSL "$OMADA_URL" -o "$OMADA_PKG"
-$STD dpkg -i "$OMADA_PKG"
-msg_ok "Installed Omada Controller"
-
-motd_ssh
-customize
-
-msg_info "Cleaning up"
-rm -rf "$OMADA_PKG"
-$STD apt -y autoremove
-$STD apt -y autoclean
-$STD apt -y clean
-msg_ok "Cleaned"
diff --git a/install/passbolt-install.sh b/install/passbolt-install.sh
deleted file mode 100644
index 4e682173c..000000000
--- a/install/passbolt-install.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: Slaviša Arežina (tremor021)
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://www.passbolt.com/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing dependencies"
-$STD apt install -y \
- apt-transport-https \
- python3-certbot-nginx \
- debconf-utils
-msg_ok "Installed dependencies"
-
-setup_mariadb
-MARIADB_DB_NAME="passboltdb" MARIADB_DB_USER="passbolt" MARIADB_DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)" setup_mariadb_db
-setup_deb822_repo \
- "passbolt" \
- "https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x3D1A0346C8E1802F774AEF21DE8B853FC155581D" \
- "https://download.passbolt.com/ce/debian" \
- "buster" \
- "stable"
-create_self_signed_cert "passbolt"
-
-msg_info "Setting up Passbolt (Patience)"
-export DEBIAN_FRONTEND=noninteractive
-IP_ADDR=$(hostname -I | awk '{print $1}')
-echo passbolt-ce-server passbolt/mysql-configuration boolean true | debconf-set-selections
-echo passbolt-ce-server passbolt/mysql-passbolt-username string $MARIADB_DB_USER | debconf-set-selections
-echo passbolt-ce-server passbolt/mysql-passbolt-password password $MARIADB_DB_PASS | debconf-set-selections
-echo passbolt-ce-server passbolt/mysql-passbolt-password-repeat password $MARIADB_DB_PASS | debconf-set-selections
-echo passbolt-ce-server passbolt/mysql-passbolt-dbname string $MARIADB_DB_NAME | debconf-set-selections
-echo passbolt-ce-server passbolt/nginx-configuration boolean true | debconf-set-selections
-echo passbolt-ce-server passbolt/nginx-configuration-three-choices select manual | debconf-set-selections
-echo passbolt-ce-server passbolt/nginx-domain string $IP_ADDR | debconf-set-selections
-echo passbolt-ce-server passbolt/nginx-certificate-file string /etc/ssl/passbolt/passbolt.crt | debconf-set-selections
-echo passbolt-ce-server passbolt/nginx-certificate-key-file string /etc/ssl/passbolt/passbolt.key | debconf-set-selections
-$STD apt install -y --no-install-recommends passbolt-ce-server
-msg_ok "Setup Passbolt"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/transmission-openvpn-install.sh b/install/transmission-openvpn-install.sh
index 7eeeb422c..eec848203 100644
--- a/install/transmission-openvpn-install.sh
+++ b/install/transmission-openvpn-install.sh
@@ -16,15 +16,15 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
- dnsutils \
- iputils-ping \
- ufw \
- iproute2
+ dnsutils \
+ iputils-ping \
+ ufw \
+ iproute2
mkdir -p /etc/systemd/system-preset
-echo "disable *" > /etc/systemd/system-preset/99-no-autostart.preset
+echo "disable *" >/etc/systemd/system-preset/99-no-autostart.preset
$STD apt install -y \
- transmission-daemon \
- privoxy
+ transmission-daemon \
+ privoxy
rm -f /etc/systemd/system-preset/99-no-autostart.preset
$STD systemctl preset-all
$STD systemctl disable --now transmission-daemon
@@ -49,12 +49,13 @@ chmod +x /opt/privoxy/*.sh
$STD ln -s /usr/bin/transmission-daemon /usr/local/bin/transmission-daemon
$STD update-alternatives --set iptables /usr/sbin/iptables-legacy
$STD update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
+rm -rf /opt/docker-transmission-openvpn
msg_ok "Configured transmission-openvpn"
msg_info "Creating Service"
LOCAL_SUBNETS=$(
- ip -o -4 addr show \
- | awk '!/127.0.0.1/ {
+ ip -o -4 addr show |
+ awk '!/127.0.0.1/ {
split($4, a, "/"); ip=a[1]; mask=a[2];
split(ip, o, ".");
if (mask < 8) {
@@ -66,12 +67,12 @@ LOCAL_SUBNETS=$(
} else {
print o[1]"."o[2]"."o[3]".*";
}
- }' \
- | sort -u | paste -sd, -
+ }' |
+ sort -u | paste -sd, -
)
TRANSMISSION_RPC_WHITELIST="127.0.0.*,${LOCAL_SUBNETS}"
mkdir -p /opt/transmission-openvpn
-cat < "/opt/transmission-openvpn/.env"
+cat <"/opt/transmission-openvpn/.env"
OPENVPN_USERNAME="username"
OPENVPN_PASSWORD="password"
OPENVPN_PROVIDER="PIA"
@@ -111,7 +112,7 @@ LOG_TO_STDOUT="false"
HEALTH_CHECK_HOST="google.com"
SELFHEAL="false"
EOF
-cat < /etc/systemd/system/openvpn-custom.service
+cat </etc/systemd/system/openvpn-custom.service
[Unit]
Description=Custom OpenVPN start service
After=network.target
@@ -126,15 +127,9 @@ EnvironmentFile=/opt/transmission-openvpn/.env
[Install]
WantedBy=multi-user.target
EOF
-systemctl enable --now -q openvpn-custom.service
+systemctl enable -q --now openvpn-custom
msg_ok "Created Service"
motd_ssh
customize
-
-msg_info "Cleaning up"
-$STD apt -y autoremove
-$STD apt -y autoclean
-$STD apt -y clean
-rm -rf /opt/docker-transmission-openvpn
-msg_ok "Cleaned"
+cleanup_lxc
diff --git a/install/upgopher-install.sh b/install/upgopher-install.sh
deleted file mode 100644
index 2f9acf8fe..000000000
--- a/install/upgopher-install.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: Eduardo González (wanetty)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/wanetty/upgopher
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Upgopher"
-mkdir -p /opt/upgopher
-fetch_and_deploy_gh_release "upgopher" "wanetty/upgopher" "prebuild" "latest" "/opt/upgopher" "upgopher_*_linux_amd64.tar.gz"
-chmod +x /opt/upgopher/upgopher
-mkdir -p /opt/upgopher/uploads
-msg_ok "Installed Upgopher"
-
-
-msg_info "Creating Service"
-cat </etc/systemd/system/upgopher.service
-[Unit]
-Description=Upgopher File Server
-Documentation=https://github.com/wanetty/upgopher
-After=network.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/upgopher
-ExecStart=/opt/upgopher/upgopher -port 9090 -dir /opt/upgopher/uploads
-Restart=always
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now upgopher
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/misc/build copy 2.func b/misc/build copy 2.func
new file mode 100644
index 000000000..b0b0404cd
--- /dev/null
+++ b/misc/build copy 2.func
@@ -0,0 +1,3549 @@
+#!/usr/bin/env bash
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
+# Revision: 1
+
+# ==============================================================================
+# BUILD.FUNC - LXC CONTAINER BUILD & CONFIGURATION
+# ==============================================================================
+#
+# This file provides the main build functions for creating and configuring
+# LXC containers in Proxmox VE. It handles:
+#
+# - Variable initialization and defaults
+# - Container creation and resource allocation
+# - Storage selection and management
+# - Advanced configuration and customization
+# - User interaction menus and prompts
+#
+# Usage:
+# - Sourced automatically by CT creation scripts
+# - Requires core.func and error_handler.func to be loaded first
+#
+# ==============================================================================
+
+# ==============================================================================
+# SECTION 1: INITIALIZATION & CORE VARIABLES
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# variables()
+#
+# - Initializes core variables for container creation
+# - Normalizes application name (NSAPP = lowercase, no spaces)
+# - Builds installer filename (var_install)
+# - Defines regex patterns for validation
+# - Fetches Proxmox hostname and version
+# - Generates unique session ID for tracking and logging
+# - Captures app-declared resource defaults (CPU, RAM, Disk)
+# ------------------------------------------------------------------------------
+variables() {
+ NSAPP=$(echo "${APP,,}" | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
+ var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
+ INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern.
+ PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
+ DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
+ METHOD="default" # sets the METHOD variable to "default", used for the API call.
+ RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable.
+ SESSION_ID="${RANDOM_UUID:0:8}" # Short session ID (first 8 chars of UUID) for log files
+ CTTYPE="${CTTYPE:-${CT_TYPE:-1}}"}
+
+ # Get Proxmox VE version and kernel version
+ if command -v pveversion >/dev/null 2>&1; then
+ PVEVERSION="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
+ else
+ PVEVERSION="N/A"
+ fi
+ KERNEL_VERSION=$(uname -r)
+
+ # Capture app-declared defaults (for precedence logic)
+ # These values are set by the app script BEFORE default.vars is loaded
+ # If app declares higher values than default.vars, app values take precedence
+ if [[ -n "${var_cpu:-}" && "${var_cpu}" =~ ^[0-9]+$ ]]; then
+ export APP_DEFAULT_CPU="${var_cpu}"
+ fi
+ if [[ -n "${var_ram:-}" && "${var_ram}" =~ ^[0-9]+$ ]]; then
+ export APP_DEFAULT_RAM="${var_ram}"
+ fi
+ if [[ -n "${var_disk:-}" && "${var_disk}" =~ ^[0-9]+$ ]]; then
+ export APP_DEFAULT_DISK="${var_disk}"
+ fi
+}
+
+# -----------------------------------------------------------------------------
+# Community-Scripts bootstrap loader
+# - Always sources build.func from remote
+# - Updates local core files only if build.func changed
+# - Local cache: /usr/local/community-scripts/core
+# -----------------------------------------------------------------------------
+
+# FUNC_DIR="/usr/local/community-scripts/core"
+# mkdir -p "$FUNC_DIR"
+
+# BUILD_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func"
+# BUILD_REV="$FUNC_DIR/build.rev"
+# DEVMODE="${DEVMODE:-no}"
+
+# # --- Step 1: fetch build.func content once, compute hash ---
+# build_content="$(curl -fsSL "$BUILD_URL")" || {
+# echo "❌ Failed to fetch build.func"
+# exit 1
+# }
+
+# newhash=$(printf "%s" "$build_content" | sha256sum | awk '{print $1}')
+# oldhash=$(cat "$BUILD_REV" 2>/dev/null || echo "")
+
+# # --- Step 2: if build.func changed, offer update for core files ---
+# if [ "$newhash" != "$oldhash" ]; then
+# echo "⚠️ build.func changed!"
+
+# while true; do
+# read -rp "Refresh local core files? [y/N/diff]: " ans
+# case "$ans" in
+# [Yy]*)
+# echo "$newhash" >"$BUILD_REV"
+
+# update_func_file() {
+# local file="$1"
+# local url="https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/$file"
+# local local_path="$FUNC_DIR/$file"
+
+# echo "⬇️ Downloading $file ..."
+# curl -fsSL "$url" -o "$local_path" || {
+# echo "❌ Failed to fetch $file"
+# exit 1
+# }
+# echo "✔️ Updated $file"
+# }
+
+# update_func_file core.func
+# update_func_file error_handler.func
+# update_func_file tools.func
+# break
+# ;;
+# [Dd]*)
+# for file in core.func error_handler.func tools.func; do
+# local_path="$FUNC_DIR/$file"
+# url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/$file"
+# remote_tmp="$(mktemp)"
+
+# curl -fsSL "$url" -o "$remote_tmp" || continue
+
+# if [ -f "$local_path" ]; then
+# echo "🔍 Diff for $file:"
+# diff -u "$local_path" "$remote_tmp" || echo "(no differences)"
+# else
+# echo "📦 New file $file will be installed"
+# fi
+
+# rm -f "$remote_tmp"
+# done
+# ;;
+# *)
+# echo "❌ Skipped updating local core files"
+# break
+# ;;
+# esac
+# done
+# else
+# if [ "$DEVMODE" != "yes" ]; then
+# echo "✔️ build.func unchanged → using existing local core files"
+# fi
+# fi
+
+# if [ -n "${_COMMUNITY_SCRIPTS_LOADER:-}" ]; then
+# return 0 2>/dev/null || exit 0
+# fi
+# _COMMUNITY_SCRIPTS_LOADER=1
+
+# # --- Step 3: always source local versions of the core files ---
+# source "$FUNC_DIR/core.func"
+# source "$FUNC_DIR/error_handler.func"
+# source "$FUNC_DIR/tools.func"
+
+# # --- Step 4: finally, source build.func directly from memory ---
+# # (no tmp file needed)
+# source <(printf "%s" "$build_content")
+
+# ------------------------------------------------------------------------------
+# Load core + error handler functions from community-scripts repo
+#
+# - Prefer curl if available, fallback to wget
+# - Load: core.func, error_handler.func, api.func
+# - Initialize error traps after loading
+# ------------------------------------------------------------------------------
+
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/api.func)
+
+if command -v curl >/dev/null 2>&1; then
+ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
+ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
+ load_functions
+ catch_errors
+ #echo "(build.func) Loaded core.func via curl"
+elif command -v wget >/dev/null 2>&1; then
+ source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
+ source <(wget -qO- https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
+ load_functions
+ catch_errors
+ #echo "(build.func) Loaded core.func via wget"
+fi
+
+# ==============================================================================
+# SECTION 2: PRE-FLIGHT CHECKS & SYSTEM VALIDATION
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# maxkeys_check()
+#
+# - Reads kernel keyring limits (maxkeys, maxbytes)
+# - Checks current usage for LXC user (UID 100000)
+# - Warns if usage is close to limits and suggests sysctl tuning
+# - Exits if thresholds are exceeded
+# - https://cleveruptime.com/docs/files/proc-key-users | https://docs.kernel.org/security/keys/core.html
+# ------------------------------------------------------------------------------
+
+maxkeys_check() {
+ # Read kernel parameters
+ per_user_maxkeys=$(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 0)
+ per_user_maxbytes=$(cat /proc/sys/kernel/keys/maxbytes 2>/dev/null || echo 0)
+
+ # Exit if kernel parameters are unavailable
+ if [[ "$per_user_maxkeys" -eq 0 || "$per_user_maxbytes" -eq 0 ]]; then
+ echo -e "${CROSS}${RD} Error: Unable to read kernel parameters. Ensure proper permissions.${CL}"
+ exit 1
+ fi
+
+ # Fetch key usage for user ID 100000 (typical for containers)
+ used_lxc_keys=$(awk '/100000:/ {print $2}' /proc/key-users 2>/dev/null || echo 0)
+ used_lxc_bytes=$(awk '/100000:/ {split($5, a, "/"); print a[1]}' /proc/key-users 2>/dev/null || echo 0)
+
+ # Calculate thresholds and suggested new limits
+ threshold_keys=$((per_user_maxkeys - 100))
+ threshold_bytes=$((per_user_maxbytes - 1000))
+ new_limit_keys=$((per_user_maxkeys * 2))
+ new_limit_bytes=$((per_user_maxbytes * 2))
+
+ # Check if key or byte usage is near limits
+ failure=0
+ if [[ "$used_lxc_keys" -gt "$threshold_keys" ]]; then
+ echo -e "${CROSS}${RD} Warning: Key usage is near the limit (${used_lxc_keys}/${per_user_maxkeys}).${CL}"
+ echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxkeys=${new_limit_keys}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}."
+ failure=1
+ fi
+ if [[ "$used_lxc_bytes" -gt "$threshold_bytes" ]]; then
+ echo -e "${CROSS}${RD} Warning: Key byte usage is near the limit (${used_lxc_bytes}/${per_user_maxbytes}).${CL}"
+ echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxbytes=${new_limit_bytes}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}."
+ failure=1
+ fi
+
+ # Provide next steps if issues are detected
+ if [[ "$failure" -eq 1 ]]; then
+ echo -e "${INFO} To apply changes, run: ${BOLD}service procps force-reload${CL}"
+ exit 1
+ fi
+
+ # Silent success - only show errors if they exist
+}
+
+# ==============================================================================
+# SECTION 3: CONTAINER SETUP UTILITIES
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# get_current_ip()
+#
+# - Returns current container IP depending on OS type
+# - Debian/Ubuntu: uses `hostname -I`
+# - Alpine: parses eth0 via `ip -4 addr`
+# - Returns "Unknown" if OS type cannot be determined
+# ------------------------------------------------------------------------------
+get_current_ip() {
+ if [ -f /etc/os-release ]; then
+ # Check for Debian/Ubuntu (uses hostname -I)
+ if grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
+ CURRENT_IP=$(hostname -I | awk '{print $1}')
+ # Check for Alpine (uses ip command)
+ elif grep -q 'ID=alpine' /etc/os-release; then
+ CURRENT_IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
+ else
+ CURRENT_IP="Unknown"
+ fi
+ fi
+ echo "$CURRENT_IP"
+}
+
+# ------------------------------------------------------------------------------
+# update_motd_ip()
+#
+# - Updates /etc/motd with current container IP
+# - Removes old IP entries to avoid duplicates
+# ------------------------------------------------------------------------------
+update_motd_ip() {
+ MOTD_FILE="/etc/motd"
+
+ if [ -f "$MOTD_FILE" ]; then
+ # Remove existing IP Address lines to prevent duplication
+ sed -i '/IP Address:/d' "$MOTD_FILE"
+
+ IP=$(get_current_ip)
+ # Add the new IP address
+ echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >>"$MOTD_FILE"
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# install_ssh_keys_into_ct()
+#
+# - Installs SSH keys into container root account if SSH is enabled
+# - Uses pct push or direct input to authorized_keys
+# - Falls back to warning if no keys provided
+# ------------------------------------------------------------------------------
+install_ssh_keys_into_ct() {
+ [[ "$SSH" != "yes" ]] && return 0
+
+ if [[ -n "$SSH_KEYS_FILE" && -s "$SSH_KEYS_FILE" ]]; then
+ msg_info "Installing selected SSH keys into CT ${CTID}"
+ pct exec "$CTID" -- sh -c 'mkdir -p /root/.ssh && chmod 700 /root/.ssh' || {
+ msg_error "prepare /root/.ssh failed"
+ return 1
+ }
+ pct push "$CTID" "$SSH_KEYS_FILE" /root/.ssh/authorized_keys >/dev/null 2>&1 ||
+ pct exec "$CTID" -- sh -c "cat > /root/.ssh/authorized_keys" <"$SSH_KEYS_FILE" || {
+ msg_error "write authorized_keys failed"
+ return 1
+ }
+ pct exec "$CTID" -- sh -c 'chmod 600 /root/.ssh/authorized_keys' || true
+ msg_ok "Installed SSH keys into CT ${CTID}"
+ return 0
+ fi
+
+ # Fallback: nichts ausgewählt
+ msg_warn "No SSH keys to install (skipping)."
+ return 0
+}
+
+# ------------------------------------------------------------------------------
+# find_host_ssh_keys()
+#
+# - Scans system for available SSH keys
+# - Supports defaults (~/.ssh, /etc/ssh/authorized_keys)
+# - Returns list of files containing valid SSH public keys
+# - Sets FOUND_HOST_KEY_COUNT to number of keys found
+# ------------------------------------------------------------------------------
+find_host_ssh_keys() {
+ local re='(ssh-(rsa|ed25519)|ecdsa-sha2-nistp256|sk-(ssh-ed25519|ecdsa-sha2-nistp256))'
+ local -a files=() cand=()
+ local g="${var_ssh_import_glob:-}"
+ local total=0 f base c
+
+ shopt -s nullglob
+ if [[ -n "$g" ]]; then
+ for pat in $g; do cand+=($pat); done
+ else
+ cand+=(/root/.ssh/authorized_keys /root/.ssh/authorized_keys2)
+ cand+=(/root/.ssh/*.pub)
+ cand+=(/etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/*)
+ fi
+ shopt -u nullglob
+
+ for f in "${cand[@]}"; do
+ [[ -f "$f" && -r "$f" ]] || continue
+ base="$(basename -- "$f")"
+ case "$base" in
+ known_hosts | known_hosts.* | config) continue ;;
+ id_*) [[ "$f" != *.pub ]] && continue ;;
+ esac
+
+ # CRLF safe check for host keys
+ c=$(tr -d '\r' <"$f" | awk '
+ /^[[:space:]]*#/ {next}
+ /^[[:space:]]*$/ {next}
+ {print}
+ ' | grep -E -c '"$re"' || true)
+
+ if ((c > 0)); then
+ files+=("$f")
+ total=$((total + c))
+ fi
+ done
+
+ # Fallback to /root/.ssh/authorized_keys
+ if ((${#files[@]} == 0)) && [[ -r /root/.ssh/authorized_keys ]]; then
+ if grep -E -q "$re" /root/.ssh/authorized_keys; then
+ files+=(/root/.ssh/authorized_keys)
+ total=$((total + $(grep -E -c "$re" /root/.ssh/authorized_keys || echo 0)))
+ fi
+ fi
+
+ FOUND_HOST_KEY_COUNT="$total"
+ (
+ IFS=:
+ echo "${files[*]}"
+ )
+}
+
+# ==============================================================================
+# SECTION 4: STORAGE & RESOURCE MANAGEMENT
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# _write_storage_to_vars()
+#
+# - Writes storage selection to vars file
+# - Removes old entries (commented and uncommented) to avoid duplicates
+# - Arguments: vars_file, key (var_container_storage/var_template_storage), value
+# ------------------------------------------------------------------------------
+_write_storage_to_vars() {
+ # $1 = vars_file, $2 = key (var_container_storage / var_template_storage), $3 = value
+ local vf="$1" key="$2" val="$3"
+ # remove uncommented and commented versions to avoid duplicates
+ sed -i "/^[#[:space:]]*${key}=/d" "$vf"
+ echo "${key}=${val}" >>"$vf"
+}
+
+choose_and_set_storage_for_file() {
+ # $1 = vars_file, $2 = class ('container'|'template')
+ local vf="$1" class="$2" key="" current=""
+ case "$class" in
+ container) key="var_container_storage" ;;
+ template) key="var_template_storage" ;;
+ *)
+ msg_error "Unknown storage class: $class"
+ return 1
+ ;;
+ esac
+
+ current=$(awk -F= -v k="^${key}=" '$0 ~ k {print $2; exit}' "$vf")
+
+ # If only one storage exists for the content type, auto-pick. Else always ask (your wish #4).
+ local content="rootdir"
+ [[ "$class" == "template" ]] && content="vztmpl"
+ local count
+ count=$(pvesm status -content "$content" | awk 'NR>1{print $1}' | wc -l)
+
+ if [[ "$count" -eq 1 ]]; then
+ STORAGE_RESULT=$(pvesm status -content "$content" | awk 'NR>1{print $1; exit}')
+ STORAGE_INFO=""
+ else
+ # If the current value is preselectable, we could show it, but per your requirement we always offer selection
+ select_storage "$class" || return 1
+ fi
+
+ _write_storage_to_vars "$vf" "$key" "$STORAGE_RESULT"
+
+ # Keep environment in sync for later steps (e.g. app-default save)
+ if [[ "$class" == "container" ]]; then
+ export var_container_storage="$STORAGE_RESULT"
+ export CONTAINER_STORAGE="$STORAGE_RESULT"
+ else
+ export var_template_storage="$STORAGE_RESULT"
+ export TEMPLATE_STORAGE="$STORAGE_RESULT"
+ fi
+
+ # Silent operation - no output message
+}
+
+# ==============================================================================
+# SECTION 5: CONFIGURATION & DEFAULTS MANAGEMENT
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# base_settings()
+#
+# - Defines all base/default variables for container creation
+# - Reads from environment variables (var_*)
+# - Provides fallback defaults for OS type/version
+# - App-specific values take precedence when they are HIGHER (for CPU, RAM, DISK)
+# - Sets up container type, resources, network, SSH, features, and tags
+# ------------------------------------------------------------------------------
+base_settings() {
+ # Default Settings
+ CT_TYPE=${var_unprivileged:-"1"}
+
+ # Resource allocation: App defaults take precedence if HIGHER
+ # Compare app-declared values (saved in APP_DEFAULT_*) with current var_* values
+ local final_disk="${var_disk:-4}"
+ local final_cpu="${var_cpu:-1}"
+ local final_ram="${var_ram:-1024}"
+
+ # If app declared higher values, use those instead
+ if [[ -n "${APP_DEFAULT_DISK:-}" && "${APP_DEFAULT_DISK}" =~ ^[0-9]+$ ]]; then
+ if [[ "${APP_DEFAULT_DISK}" -gt "${final_disk}" ]]; then
+ final_disk="${APP_DEFAULT_DISK}"
+ fi
+ fi
+
+ if [[ -n "${APP_DEFAULT_CPU:-}" && "${APP_DEFAULT_CPU}" =~ ^[0-9]+$ ]]; then
+ if [[ "${APP_DEFAULT_CPU}" -gt "${final_cpu}" ]]; then
+ final_cpu="${APP_DEFAULT_CPU}"
+ fi
+ fi
+
+ if [[ -n "${APP_DEFAULT_RAM:-}" && "${APP_DEFAULT_RAM}" =~ ^[0-9]+$ ]]; then
+ if [[ "${APP_DEFAULT_RAM}" -gt "${final_ram}" ]]; then
+ final_ram="${APP_DEFAULT_RAM}"
+ fi
+ fi
+
+ DISK_SIZE="${final_disk}"
+ CORE_COUNT="${final_cpu}"
+ RAM_SIZE="${final_ram}"
+ VERBOSE=${var_verbose:-"${1:-no}"}
+ PW=${var_pw:-""}
+ CT_ID=${var_ctid:-$NEXTID}
+ HN=${var_hostname:-$NSAPP}
+ BRG=${var_brg:-"vmbr0"}
+ NET=${var_net:-"dhcp"}
+ IPV6_METHOD=${var_ipv6_method:-"none"}
+ IPV6_STATIC=${var_ipv6_static:-""}
+ GATE=${var_gateway:-""}
+ APT_CACHER=${var_apt_cacher:-""}
+ APT_CACHER_IP=${var_apt_cacher_ip:-""}
+
+ # Runtime check: Verify APT cacher is reachable if configured
+ if [[ -n "$APT_CACHER_IP" && "$APT_CACHER" == "yes" ]]; then
+ if ! curl -s --connect-timeout 2 "http://${APT_CACHER_IP}:3142" >/dev/null 2>&1; then
+ msg_warn "APT Cacher configured but not reachable at ${APT_CACHER_IP}:3142"
+ msg_custom "⚠️" "${YW}" "Disabling APT Cacher for this installation"
+ APT_CACHER=""
+ APT_CACHER_IP=""
+ else
+ msg_ok "APT Cacher verified at ${APT_CACHER_IP}:3142"
+ fi
+ fi
+
+ MTU=${var_mtu:-""}
+ SD=${var_storage:-""}
+ NS=${var_ns:-""}
+ MAC=${var_mac:-""}
+ VLAN=${var_vlan:-""}
+ SSH=${var_ssh:-"no"}
+ SSH_AUTHORIZED_KEY=${var_ssh_authorized_key:-""}
+ UDHCPC_FIX=${var_udhcpc_fix:-""}
+ TAGS="community-script,${var_tags:-}"
+ ENABLE_FUSE=${var_fuse:-"${1:-no}"}
+ ENABLE_TUN=${var_tun:-"${1:-no}"}
+
+ # Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
+ if [ -z "$var_os" ]; then
+ var_os="debian"
+ fi
+ if [ -z "$var_version" ]; then
+ var_version="12"
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# default_var_settings
+#
+# - Ensures /usr/local/community-scripts/default.vars exists (creates if missing)
+# - Loads var_* values from default.vars (safe parser, no source/eval)
+# - Precedence: ENV var_* > default.vars > built-in defaults
+# - Maps var_verbose → VERBOSE
+# - Calls base_settings "$VERBOSE" and echo_default
+# ------------------------------------------------------------------------------
+default_var_settings() {
+ # Allowed var_* keys (alphabetically sorted)
+ # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
+ local VAR_WHITELIST=(
+ var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse
+ var_gateway var_hostname var_ipv6_method var_mac var_mtu
+ var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged
+ var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
+ )
+
+ # Snapshot: environment variables (highest precedence)
+ declare -A _HARD_ENV=()
+ local _k
+ for _k in "${VAR_WHITELIST[@]}"; do
+ if printenv "$_k" >/dev/null 2>&1; then _HARD_ENV["$_k"]=1; fi
+ done
+
+ # Find default.vars location
+ local _find_default_vars
+ _find_default_vars() {
+ local f
+ for f in \
+ /usr/local/community-scripts/default.vars \
+ "$HOME/.config/community-scripts/default.vars" \
+ "./default.vars"; do
+ [ -f "$f" ] && {
+ echo "$f"
+ return 0
+ }
+ done
+ return 1
+ }
+ # Allow override of storages via env (for non-interactive use cases)
+ [ -n "${var_template_storage:-}" ] && TEMPLATE_STORAGE="$var_template_storage"
+ [ -n "${var_container_storage:-}" ] && CONTAINER_STORAGE="$var_container_storage"
+
+ # Create once, with storages already selected, no var_ctid/var_hostname lines
+ local _ensure_default_vars
+ _ensure_default_vars() {
+ _find_default_vars >/dev/null 2>&1 && return 0
+
+ local canonical="/usr/local/community-scripts/default.vars"
+ # Silent creation - no msg_info output
+ mkdir -p /usr/local/community-scripts
+
+ # Pick storages before writing the file (always ask unless only one)
+ # Create a minimal temp file to write into
+ : >"$canonical"
+
+ # Base content (no var_ctid / var_hostname here)
+ cat >"$canonical" <<'EOF'
+# Community-Scripts defaults (var_* only). Lines starting with # are comments.
+# Precedence: ENV var_* > default.vars > built-ins.
+# Keep keys alphabetically sorted.
+
+# Container type
+var_unprivileged=1
+
+# Resources
+var_cpu=1
+var_disk=4
+var_ram=1024
+
+# Network
+var_brg=vmbr0
+var_net=dhcp
+var_ipv6_method=none
+# var_gateway=
+# var_vlan=
+# var_mtu=
+# var_mac=
+# var_ns=
+
+# SSH
+var_ssh=no
+# var_ssh_authorized_key=
+
+# APT cacher (optional - with example)
+# var_apt_cacher=yes
+# var_apt_cacher_ip=192.168.1.10
+
+# Features/Tags/verbosity
+var_fuse=no
+var_tun=no
+var_tags=community-script
+var_verbose=no
+
+# Security (root PW) – empty => autologin
+# var_pw=
+EOF
+
+ # Now choose storages (always prompt unless just one exists)
+ choose_and_set_storage_for_file "$canonical" template
+ choose_and_set_storage_for_file "$canonical" container
+
+ chmod 0644 "$canonical"
+ # Silent creation - no output message
+ }
+
+ # Whitelist check
+ local _is_whitelisted_key
+ _is_whitelisted_key() {
+ local k="$1"
+ local w
+ for w in "${VAR_WHITELIST[@]}"; do [ "$k" = "$w" ] && return 0; done
+ return 1
+ }
+
+ # Safe parser for KEY=VALUE lines
+ local _load_vars_file
+ _load_vars_file() {
+ local file="$1"
+ [ -f "$file" ] || return 0
+ msg_info "Loading defaults from ${file}"
+ local line key val
+ while IFS= read -r line || [ -n "$line" ]; do
+ line="${line#"${line%%[![:space:]]*}"}"
+ line="${line%"${line##*[![:space:]]}"}"
+ [[ -z "$line" || "$line" == \#* ]] && continue
+ if [[ "$line" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
+ local var_key="${BASH_REMATCH[1]}"
+ local var_val="${BASH_REMATCH[2]}"
+
+ [[ "$var_key" != var_* ]] && continue
+ _is_whitelisted_key "$var_key" || {
+ msg_debug "Ignore non-whitelisted ${var_key}"
+ continue
+ }
+
+ # Strip quotes
+ if [[ "$var_val" =~ ^\"(.*)\"$ ]]; then
+ var_val="${BASH_REMATCH[1]}"
+ elif [[ "$var_val" =~ ^\'(.*)\'$ ]]; then
+ var_val="${BASH_REMATCH[1]}"
+ fi
+
+ # Unsafe characters
+ case $var_val in
+ \"*\")
+ var_val=${var_val#\"}
+ var_val=${var_val%\"}
+ ;;
+ \'*\')
+ var_val=${var_val#\'}
+ var_val=${var_val%\'}
+ ;;
+ esac # Hard env wins
+ [[ -n "${_HARD_ENV[$var_key]:-}" ]] && continue
+ # Set only if not already exported
+ [[ -z "${!var_key+x}" ]] && export "${var_key}=${var_val}"
+ else
+ msg_warn "Malformed line in ${file}: ${line}"
+ fi
+ done <"$file"
+ msg_ok "Loaded ${file}"
+ }
+
+ # 1) Ensure file exists
+ _ensure_default_vars
+
+ # 2) Load file
+ local dv
+ dv="$(_find_default_vars)" || {
+ msg_error "default.vars not found after ensure step"
+ return 1
+ }
+ _load_vars_file "$dv"
+
+ # 3) Map var_verbose → VERBOSE
+ if [[ -n "${var_verbose:-}" ]]; then
+ case "${var_verbose,,}" in 1 | yes | true | on) VERBOSE="yes" ;; 0 | no | false | off) VERBOSE="no" ;; *) VERBOSE="${var_verbose}" ;; esac
+ else
+ VERBOSE="no"
+ fi
+
+ # 4) Apply base settings and show summary
+ METHOD="mydefaults-global"
+ base_settings "$VERBOSE"
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using My Defaults (default.vars) on node $PVEHOST_NAME${CL}"
+ echo_default
+}
+
+# ------------------------------------------------------------------------------
+# get_app_defaults_path()
+#
+# - Returns full path for app-specific defaults file
+# - Example: /usr/local/community-scripts/defaults/.vars
+# ------------------------------------------------------------------------------
+
+get_app_defaults_path() {
+ local n="${NSAPP:-${APP,,}}"
+ echo "/usr/local/community-scripts/defaults/${n}.vars"
+}
+
+# ------------------------------------------------------------------------------
+# maybe_offer_save_app_defaults
+#
+# - Called after advanced_settings returned with fully chosen values.
+# - If no .vars exists, offers to persist current advanced settings
+# into /usr/local/community-scripts/defaults/.vars
+# - Only writes whitelisted var_* keys.
+# - Extracts raw values from flags like ",gw=..." ",mtu=..." etc.
+# ------------------------------------------------------------------------------
+if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then
+ # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
+ declare -ag VAR_WHITELIST=(
+ var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse
+ var_gateway var_hostname var_ipv6_method var_mac var_mtu
+ var_net var_ns var_pw var_ram var_tags var_tun var_unprivileged
+ var_verbose var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
+ )
+fi
+
+# Note: _is_whitelisted_key() is defined above in default_var_settings section
+
+_sanitize_value() {
+ # Disallow Command-Substitution / Shell-Meta
+ case "$1" in
+ *'$('* | *'`'* | *';'* | *'&'* | *'<('*)
+ echo ""
+ return 0
+ ;;
+ esac
+ echo "$1"
+}
+
+# Map-Parser: read var_* from file into _VARS_IN associative array
+# Note: Main _load_vars_file() with full validation is defined in default_var_settings section
+# This simplified version is used specifically for diff operations via _VARS_IN array
+declare -A _VARS_IN
+_load_vars_file_to_map() {
+ local file="$1"
+ [ -f "$file" ] || return 0
+ _VARS_IN=() # Clear array
+ local line key val
+ while IFS= read -r line || [ -n "$line" ]; do
+ line="${line#"${line%%[![:space:]]*}"}"
+ line="${line%"${line##*[![:space:]]}"}"
+ [ -z "$line" ] && continue
+ case "$line" in
+ \#*) continue ;;
+ esac
+ key=$(printf "%s" "$line" | cut -d= -f1)
+ val=$(printf "%s" "$line" | cut -d= -f2-)
+ case "$key" in
+ var_*)
+ if _is_whitelisted_key "$key"; then
+ _VARS_IN["$key"]="$val"
+ fi
+ ;;
+ esac
+ done <"$file"
+}
+
+# Diff function for two var_* files -> produces human-readable diff list for $1 (old) vs $2 (new)
+_build_vars_diff() {
+ local oldf="$1" newf="$2"
+ local k
+ local -A OLD=() NEW=()
+ _load_vars_file_to_map "$oldf"
+ for k in "${!_VARS_IN[@]}"; do OLD["$k"]="${_VARS_IN[$k]}"; done
+ _load_vars_file_to_map "$newf"
+ for k in "${!_VARS_IN[@]}"; do NEW["$k"]="${_VARS_IN[$k]}"; done
+
+ local out
+ out+="# Diff for ${APP} (${NSAPP})\n"
+ out+="# Old: ${oldf}\n# New: ${newf}\n\n"
+
+ local found_change=0
+
+ # Changed & Removed
+ for k in "${!OLD[@]}"; do
+ if [[ -v NEW["$k"] ]]; then
+ if [[ "${OLD[$k]}" != "${NEW[$k]}" ]]; then
+ out+="~ ${k}\n - old: ${OLD[$k]}\n + new: ${NEW[$k]}\n"
+ found_change=1
+ fi
+ else
+ out+="- ${k}\n - old: ${OLD[$k]}\n"
+ found_change=1
+ fi
+ done
+
+ # Added
+ for k in "${!NEW[@]}"; do
+ if [[ ! -v OLD["$k"] ]]; then
+ out+="+ ${k}\n + new: ${NEW[$k]}\n"
+ found_change=1
+ fi
+ done
+
+ if [[ $found_change -eq 0 ]]; then
+ out+="(No differences)\n"
+ fi
+
+ printf "%b" "$out"
+}
+
+# Build a temporary .vars file from current advanced settings
+_build_current_app_vars_tmp() {
+ tmpf="$(mktemp /tmp/${NSAPP:-app}.vars.new.XXXXXX)"
+
+ # NET/GW
+ _net="${NET:-}"
+ _gate=""
+ case "${GATE:-}" in
+ ,gw=*) _gate=$(echo "$GATE" | sed 's/^,gw=//') ;;
+ esac
+
+ # IPv6
+ _ipv6_method="${IPV6_METHOD:-auto}"
+ _ipv6_static=""
+ _ipv6_gateway=""
+ if [ "$_ipv6_method" = "static" ]; then
+ _ipv6_static="${IPV6_ADDR:-}"
+ _ipv6_gateway="${IPV6_GATE:-}"
+ fi
+
+ # MTU/VLAN/MAC
+ _mtu=""
+ _vlan=""
+ _mac=""
+ case "${MTU:-}" in
+ ,mtu=*) _mtu=$(echo "$MTU" | sed 's/^,mtu=//') ;;
+ esac
+ case "${VLAN:-}" in
+ ,tag=*) _vlan=$(echo "$VLAN" | sed 's/^,tag=//') ;;
+ esac
+ case "${MAC:-}" in
+ ,hwaddr=*) _mac=$(echo "$MAC" | sed 's/^,hwaddr=//') ;;
+ esac
+
+ # DNS / Searchdomain
+ _ns=""
+ _searchdomain=""
+ case "${NS:-}" in
+ -nameserver=*) _ns=$(echo "$NS" | sed 's/^-nameserver=//') ;;
+ esac
+ case "${SD:-}" in
+ -searchdomain=*) _searchdomain=$(echo "$SD" | sed 's/^-searchdomain=//') ;;
+ esac
+
+ # SSH / APT / Features
+ _ssh="${SSH:-no}"
+ _ssh_auth="${SSH_AUTHORIZED_KEY:-}"
+ _apt_cacher="${APT_CACHER:-}"
+ _apt_cacher_ip="${APT_CACHER_IP:-}"
+ _fuse="${ENABLE_FUSE:-no}"
+ _tun="${ENABLE_TUN:-no}"
+ _tags="${TAGS:-}"
+ _verbose="${VERBOSE:-no}"
+
+ # Type / Resources / Identity
+ _unpriv="${CT_TYPE:-1}"
+ _cpu="${CORE_COUNT:-1}"
+ _ram="${RAM_SIZE:-1024}"
+ _disk="${DISK_SIZE:-4}"
+ _hostname="${HN:-$NSAPP}"
+
+ # Storage
+ _tpl_storage="${TEMPLATE_STORAGE:-${var_template_storage:-}}"
+ _ct_storage="${CONTAINER_STORAGE:-${var_container_storage:-}}"
+
+ {
+ echo "# App-specific defaults for ${APP} (${NSAPP})"
+ echo "# Generated on $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
+ echo
+
+ echo "var_unprivileged=$(_sanitize_value "$_unpriv")"
+ echo "var_cpu=$(_sanitize_value "$_cpu")"
+ echo "var_ram=$(_sanitize_value "$_ram")"
+ echo "var_disk=$(_sanitize_value "$_disk")"
+
+ [ -n "${BRG:-}" ] && echo "var_brg=$(_sanitize_value "$BRG")"
+ [ -n "$_net" ] && echo "var_net=$(_sanitize_value "$_net")"
+ [ -n "$_gate" ] && echo "var_gateway=$(_sanitize_value "$_gate")"
+ [ -n "$_mtu" ] && echo "var_mtu=$(_sanitize_value "$_mtu")"
+ [ -n "$_vlan" ] && echo "var_vlan=$(_sanitize_value "$_vlan")"
+ [ -n "$_mac" ] && echo "var_mac=$(_sanitize_value "$_mac")"
+ [ -n "$_ns" ] && echo "var_ns=$(_sanitize_value "$_ns")"
+
+ [ -n "$_ipv6_method" ] && echo "var_ipv6_method=$(_sanitize_value "$_ipv6_method")"
+ # var_ipv6_static removed - static IPs are unique, can't be default
+
+ [ -n "$_ssh" ] && echo "var_ssh=$(_sanitize_value "$_ssh")"
+ [ -n "$_ssh_auth" ] && echo "var_ssh_authorized_key=$(_sanitize_value "$_ssh_auth")"
+
+ [ -n "$_apt_cacher" ] && echo "var_apt_cacher=$(_sanitize_value "$_apt_cacher")"
+ [ -n "$_apt_cacher_ip" ] && echo "var_apt_cacher_ip=$(_sanitize_value "$_apt_cacher_ip")"
+
+ [ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
+ [ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")"
+ [ -n "$_tags" ] && echo "var_tags=$(_sanitize_value "$_tags")"
+ [ -n "$_verbose" ] && echo "var_verbose=$(_sanitize_value "$_verbose")"
+
+ [ -n "$_hostname" ] && echo "var_hostname=$(_sanitize_value "$_hostname")"
+ [ -n "$_searchdomain" ] && echo "var_searchdomain=$(_sanitize_value "$_searchdomain")"
+
+ [ -n "$_tpl_storage" ] && echo "var_template_storage=$(_sanitize_value "$_tpl_storage")"
+ [ -n "$_ct_storage" ] && echo "var_container_storage=$(_sanitize_value "$_ct_storage")"
+ } >"$tmpf"
+
+ echo "$tmpf"
+}
+
+# ------------------------------------------------------------------------------
+# maybe_offer_save_app_defaults()
+#
+# - Called after advanced_settings()
+# - Offers to save current values as app defaults if not existing
+# - If file exists: shows diff and allows Update, Keep, View Diff, or Cancel
+# ------------------------------------------------------------------------------
+maybe_offer_save_app_defaults() {
+ local app_vars_path
+ app_vars_path="$(get_app_defaults_path)"
+
+ # always build from current settings
+ local new_tmp diff_tmp
+ new_tmp="$(_build_current_app_vars_tmp)"
+ diff_tmp="$(mktemp -p /tmp "${NSAPP:-app}.vars.diff.XXXXXX")"
+
+ # 1) if no file → offer to create
+ if [[ ! -f "$app_vars_path" ]]; then
+ if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --yesno "Save these advanced settings as defaults for ${APP}?\n\nThis will create:\n${app_vars_path}" 12 72; then
+ mkdir -p "$(dirname "$app_vars_path")"
+ install -m 0644 "$new_tmp" "$app_vars_path"
+ msg_ok "Saved app defaults: ${app_vars_path}"
+ fi
+ rm -f "$new_tmp" "$diff_tmp"
+ return 0
+ fi
+
+ # 2) if file exists → build diff
+ _build_vars_diff "$app_vars_path" "$new_tmp" >"$diff_tmp"
+
+ # if no differences → do nothing
+ if grep -q "^(No differences)$" "$diff_tmp"; then
+ rm -f "$new_tmp" "$diff_tmp"
+ return 0
+ fi
+
+ # 3) if file exists → show menu with default selection "Update Defaults"
+ local app_vars_file
+ app_vars_file="$(basename "$app_vars_path")"
+
+ while true; do
+ local sel
+ sel="$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "APP DEFAULTS – ${APP}" \
+ --menu "Differences detected. What do you want to do?" 20 78 10 \
+ "Update Defaults" "Write new values to ${app_vars_file}" \
+ "Keep Current" "Keep existing defaults (no changes)" \
+ "View Diff" "Show a detailed diff" \
+ "Cancel" "Abort without changes" \
+ --default-item "Update Defaults" \
+ 3>&1 1>&2 2>&3)" || { sel="Cancel"; }
+
+ case "$sel" in
+ "Update Defaults")
+ install -m 0644 "$new_tmp" "$app_vars_path"
+ msg_ok "Updated app defaults: ${app_vars_path}"
+ break
+ ;;
+ "Keep Current")
+ msg_custom "ℹ️" "${BL}" "Keeping current app defaults: ${app_vars_path}"
+ break
+ ;;
+ "View Diff")
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "Diff – ${APP}" \
+ --scrolltext --textbox "$diff_tmp" 25 100
+ ;;
+ "Cancel" | *)
+ msg_custom "🚫" "${YW}" "Canceled. No changes to app defaults."
+ break
+ ;;
+ esac
+ done
+
+ rm -f "$new_tmp" "$diff_tmp"
+}
+
+ensure_storage_selection_for_vars_file() {
+ local vf="$1"
+
+ # Read stored values (if any)
+ local tpl ct
+ tpl=$(grep -E '^var_template_storage=' "$vf" | cut -d= -f2-)
+ ct=$(grep -E '^var_container_storage=' "$vf" | cut -d= -f2-)
+
+ if [[ -n "$tpl" && -n "$ct" ]]; then
+ TEMPLATE_STORAGE="$tpl"
+ CONTAINER_STORAGE="$ct"
+ return 0
+ fi
+
+ choose_and_set_storage_for_file "$vf" template
+ choose_and_set_storage_for_file "$vf" container
+
+ # Silent operation - no output message
+}
+
+ensure_global_default_vars_file() {
+ local vars_path="/usr/local/community-scripts/default.vars"
+ if [[ ! -f "$vars_path" ]]; then
+ mkdir -p "$(dirname "$vars_path")"
+ touch "$vars_path"
+ fi
+ echo "$vars_path"
+}
+
+# ==============================================================================
+# SECTION 6: ADVANCED INTERACTIVE CONFIGURATION
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# advanced_settings()
+#
+# - Interactive whiptail menu for comprehensive container configuration
+# - Allows user to customize:
+# * Container type (privileged/unprivileged)
+# * Root password
+# * Container ID (CTID)
+# * Hostname
+# * Resources (disk size, CPU cores, RAM)
+# * Network (IPv4/IPv6, gateway, DNS, MAC, VLAN, MTU)
+# * SSH settings and key injection
+# * Advanced features (FUSE, TUN, keyctl)
+# * Tags for organization
+# * Verbose/debug mode
+# - Loops until user confirms or cancels
+# - Validates all input and shows current selections
+# ------------------------------------------------------------------------------
+advanced_settings() {
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Here is an instructional tip:" "To make a selection, use the Spacebar." 8 58
+ # Setting Default Tag for Advanced Settings
+ TAGS="community-script;${var_tags:-}"
+ CT_DEFAULT_TYPE="${CT_TYPE}"
+ CT_TYPE=""
+ while [ -z "$CT_TYPE" ]; do
+ if [ "$CT_DEFAULT_TYPE" == "1" ]; then
+ if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
+ "1" "Unprivileged" ON \
+ "0" "Privileged" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ -n "$CT_TYPE" ]; then
+ CT_TYPE_DESC="Unprivileged"
+ if [ "$CT_TYPE" -eq 0 ]; then
+ CT_TYPE_DESC="Privileged"
+ fi
+ echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
+ echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os |${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
+ fi
+ else
+ exit_script
+ fi
+ fi
+ if [ "$CT_DEFAULT_TYPE" == "0" ]; then
+ if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
+ "1" "Unprivileged" OFF \
+ "0" "Privileged" ON \
+ 3>&1 1>&2 2>&3); then
+ if [ -n "$CT_TYPE" ]; then
+ CT_TYPE_DESC="Unprivileged"
+ if [ "$CT_TYPE" -eq 0 ]; then
+ CT_TYPE_DESC="Privileged"
+ fi
+ echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
+ echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
+ echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
+ fi
+ else
+ exit_script
+ fi
+ fi
+ done
+
+ while true; do
+ if PW1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
+ # Empty = Autologin
+ if [[ -z "$PW1" ]]; then
+ PW=""
+ PW1="Automatic Login"
+ echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
+ break
+ fi
+
+ # Invalid: contains spaces
+ if [[ "$PW1" == *" "* ]]; then
+ whiptail --msgbox "Password cannot contain spaces." 8 58
+ continue
+ fi
+
+ # Invalid: too short
+ if ((${#PW1} < 5)); then
+ whiptail --msgbox "Password must be at least 5 characters." 8 58
+ continue
+ fi
+
+ # Confirm password
+ if PW2=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
+ if [[ "$PW1" == "$PW2" ]]; then
+ PW="-password $PW1"
+ echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
+ break
+ else
+ whiptail --msgbox "Passwords do not match. Please try again." 8 58
+ fi
+ else
+ exit_script
+ fi
+ else
+ exit_script
+ fi
+ done
+
+ if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 "$NEXTID" --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
+ if [ -z "$CT_ID" ]; then
+ CT_ID="$NEXTID"
+ fi
+ else
+ exit_script
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
+
+ while true; do
+ if CT_NAME=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 "$NSAPP" --title "HOSTNAME" 3>&1 1>&2 2>&3); then
+ if [ -z "$CT_NAME" ]; then
+ HN="$NSAPP"
+ else
+ HN=$(echo "${CT_NAME,,}" | tr -d ' ')
+ fi
+ # Hostname validate (RFC 1123)
+ if [[ "$HN" =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ ]]; then
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ break
+ else
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --msgbox "❌ Invalid hostname: '$HN'\n\nOnly lowercase letters, digits and hyphens (-) are allowed.\nUnderscores (_) or other characters are not permitted!" 10 70
+ fi
+ else
+ exit_script
+ fi
+ done
+
+ while true; do
+ DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 "$var_disk" --title "DISK SIZE" 3>&1 1>&2 2>&3) || exit_script
+
+ if [ -z "$DISK_SIZE" ]; then
+ DISK_SIZE="$var_disk"
+ fi
+
+ if [[ "$DISK_SIZE" =~ ^[1-9][0-9]*$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
+ break
+ else
+ whiptail --msgbox "Disk size must be a positive integer!" 8 58
+ fi
+ done
+
+ while true; do
+ CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
+ --inputbox "Allocate CPU Cores" 8 58 "$var_cpu" --title "CORE COUNT" 3>&1 1>&2 2>&3) || exit_script
+
+ if [ -z "$CORE_COUNT" ]; then
+ CORE_COUNT="$var_cpu"
+ fi
+
+ if [[ "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ break
+ else
+ whiptail --msgbox "CPU core count must be a positive integer!" 8 58
+ fi
+ done
+
+ while true; do
+ RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
+ --inputbox "Allocate RAM in MiB" 8 58 "$var_ram" --title "RAM" 3>&1 1>&2 2>&3) || exit_script
+
+ if [ -z "$RAM_SIZE" ]; then
+ RAM_SIZE="$var_ram"
+ fi
+
+ if [[ "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
+ break
+ else
+ whiptail --msgbox "RAM size must be a positive integer!" 8 58
+ fi
+ done
+
+ IFACE_FILEPATH_LIST="/etc/network/interfaces"$'\n'$(find "/etc/network/interfaces.d/" -type f)
+ BRIDGES=""
+ OLD_IFS=$IFS
+ IFS=$'\n'
+ for iface_filepath in ${IFACE_FILEPATH_LIST}; do
+
+ iface_indexes_tmpfile=$(mktemp -q -u '.iface-XXXX')
+ (grep -Pn '^\s*iface' "${iface_filepath}" | cut -d':' -f1 && wc -l "${iface_filepath}" | cut -d' ' -f1) | awk 'FNR==1 {line=$0; next} {print line":"$0-1; line=$0}' >"${iface_indexes_tmpfile}" || true
+
+ if [ -f "${iface_indexes_tmpfile}" ]; then
+
+ while read -r pair; do
+ start=$(echo "${pair}" | cut -d':' -f1)
+ end=$(echo "${pair}" | cut -d':' -f2)
+
+ if awk "NR >= ${start} && NR <= ${end}" "${iface_filepath}" | grep -qP '^\s*(bridge[-_](ports|stp|fd|vlan-aware|vids)|ovs_type\s+OVSBridge)\b'; then
+ iface_name=$(sed "${start}q;d" "${iface_filepath}" | awk '{print $2}')
+ BRIDGES="${iface_name}"$'\n'"${BRIDGES}"
+ fi
+
+ done <"${iface_indexes_tmpfile}"
+ rm -f "${iface_indexes_tmpfile}"
+ fi
+
+ done
+ IFS=$OLD_IFS
+ BRIDGES=$(echo "$BRIDGES" | grep -v '^\s*$' | sort | uniq)
+ if [[ -z "$BRIDGES" ]]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ # Build bridge menu with descriptions
+ BRIDGE_MENU_OPTIONS=()
+ while IFS= read -r bridge; do
+ if [[ -n "$bridge" ]]; then
+ # Get description from Proxmox built-in method - find comment for this specific bridge
+ description=$(grep -A 10 "iface $bridge" /etc/network/interfaces | grep '^#' | head -n1 | sed 's/^#\s*//')
+ if [[ -n "$description" ]]; then
+ BRIDGE_MENU_OPTIONS+=("$bridge" "${description}")
+ else
+ BRIDGE_MENU_OPTIONS+=("$bridge" " ")
+ fi
+ fi
+ done <<<"$BRIDGES"
+
+ BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --menu "Select network bridge: " 18 55 6 "${BRIDGE_MENU_OPTIONS[@]}" 3>&1 1>&2 2>&3)
+ if [[ -z "$BRG" ]]; then
+ exit_script
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
+ fi
+
+ # IPv4 methods: dhcp, static, none
+ while true; do
+ IPV4_METHOD=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "IPv4 Address Management" \
+ --menu "Select IPv4 Address Assignment Method:" 12 60 2 \
+ "dhcp" "Automatic (DHCP, recommended)" \
+ "static" "Static (manual entry)" \
+ 3>&1 1>&2 2>&3)
+
+ exit_status=$?
+ if [ $exit_status -ne 0 ]; then
+ exit_script
+ fi
+
+ case "$IPV4_METHOD" in
+ dhcp)
+ NET="dhcp"
+ GATE=""
+ echo -e "${NETWORK}${BOLD}${DGN}IPv4: DHCP${CL}"
+ break
+ ;;
+ static)
+ # Static: call and validate CIDR address
+ while true; do
+ NET=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --inputbox "Enter Static IPv4 CIDR Address (e.g. 192.168.100.50/24)" 8 58 "" \
+ --title "IPv4 ADDRESS" 3>&1 1>&2 2>&3)
+ if [ -z "$NET" ]; then
+ whiptail --msgbox "IPv4 address must not be empty." 8 58
+ continue
+ elif [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then
+ echo -e "${NETWORK}${BOLD}${DGN}IPv4 Address: ${BGN}$NET${CL}"
+ break
+ else
+ whiptail --msgbox "$NET is not a valid IPv4 CIDR address. Please enter a correct value!" 8 58
+ fi
+ done
+
+ # call and validate Gateway
+ while true; do
+ GATE1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --inputbox "Enter Gateway IP address for static IPv4" 8 58 "" \
+ --title "Gateway IP" 3>&1 1>&2 2>&3)
+ if [ -z "$GATE1" ]; then
+ whiptail --msgbox "Gateway IP address cannot be empty." 8 58
+ elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
+ whiptail --msgbox "Invalid Gateway IP address format." 8 58
+ else
+ GATE=",gw=$GATE1"
+ echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
+ break
+ fi
+ done
+ break
+ ;;
+ esac
+ done
+
+ # IPv6 Address Management selection
+ while true; do
+ IPV6_METHOD=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --menu \
+ "Select IPv6 Address Management Type:" 15 58 4 \
+ "auto" "SLAAC/AUTO (recommended, default)" \
+ "dhcp" "DHCPv6" \
+ "static" "Static (manual entry)" \
+ "none" "Disabled" \
+ --default-item "auto" 3>&1 1>&2 2>&3)
+ [ $? -ne 0 ] && exit_script
+
+ case "$IPV6_METHOD" in
+ auto)
+ echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}SLAAC/AUTO${CL}"
+ IPV6_ADDR=""
+ IPV6_GATE=""
+ break
+ ;;
+ dhcp)
+ echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}DHCPv6${CL}"
+ IPV6_ADDR="dhcp"
+ IPV6_GATE=""
+ break
+ ;;
+ static)
+ # Ask for static IPv6 address (CIDR notation, e.g., 2001:db8::1234/64)
+ while true; do
+ IPV6_ADDR=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox \
+ "Set a static IPv6 CIDR address (e.g., 2001:db8::1234/64)" 8 58 "" \
+ --title "IPv6 STATIC ADDRESS" 3>&1 1>&2 2>&3) || exit_script
+ if [[ "$IPV6_ADDR" =~ ^([0-9a-fA-F:]+:+)+[0-9a-fA-F]+(/[0-9]{1,3})$ ]]; then
+ echo -e "${NETWORK}${BOLD}${DGN}IPv6 Address: ${BGN}$IPV6_ADDR${CL}"
+ break
+ else
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox \
+ "$IPV6_ADDR is an invalid IPv6 CIDR address. Please enter a valid IPv6 CIDR address (e.g., 2001:db8::1234/64)" 8 58
+ fi
+ done
+ # Optional: ask for IPv6 gateway for static config
+ while true; do
+ IPV6_GATE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox \
+ "Enter IPv6 gateway address (optional, leave blank for none)" 8 58 "" --title "IPv6 GATEWAY" 3>&1 1>&2 2>&3)
+ if [ -z "$IPV6_GATE" ]; then
+ IPV6_GATE=""
+ break
+ elif [[ "$IPV6_GATE" =~ ^([0-9a-fA-F:]+:+)+[0-9a-fA-F]+$ ]]; then
+ break
+ else
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox \
+ "Invalid IPv6 gateway format." 8 58
+ fi
+ done
+ break
+ ;;
+ none)
+ echo -e "${NETWORK}${BOLD}${DGN}IPv6: ${BGN}Disabled${CL}"
+ IPV6_ADDR="none"
+ IPV6_GATE=""
+ break
+ ;;
+ *)
+ exit_script
+ ;;
+ esac
+ done
+
+ if [ "$var_os" == "alpine" ]; then
+ APT_CACHER=""
+ APT_CACHER_IP=""
+ else
+ if APT_CACHER_IP=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then
+ APT_CACHER="${APT_CACHER_IP:+yes}"
+ echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}"
+ else
+ exit_script
+ fi
+ fi
+
+ # if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "IPv6" --yesno "Disable IPv6?" 10 58); then
+ # DISABLEIP6="yes"
+ # else
+ # DISABLEIP6="no"
+ # fi
+ # echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}$DISABLEIP6${CL}"
+
+ if MTU1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default [The MTU of your selected vmbr, default is 1500])" 8 58 --title "MTU SIZE" 3>&1 1>&2 2>&3); then
+ if [ -z "$MTU1" ]; then
+ MTU1="Default"
+ MTU=""
+ else
+ MTU=",mtu=$MTU1"
+ fi
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ exit_script
+ fi
+
+ if SD=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Search Domain (leave blank for HOST)" 8 58 --title "DNS Search Domain" 3>&1 1>&2 2>&3); then
+ if [ -z "$SD" ]; then
+ SX=Host
+ SD=""
+ else
+ SX=$SD
+ SD="-searchdomain=$SD"
+ fi
+ echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SX${CL}"
+ else
+ exit_script
+ fi
+
+ if NX=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Server IP (leave blank for HOST)" 8 58 --title "DNS SERVER IP" 3>&1 1>&2 2>&3); then
+ if [ -z "$NX" ]; then
+ NX=Host
+ NS=""
+ else
+ NS="-nameserver=$NX"
+ fi
+ echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}"
+ else
+ exit_script
+ fi
+
+ if [ "$var_os" == "alpine" ] && [ "$NET" == "dhcp" ] && [ "$NX" != "Host" ]; then
+ UDHCPC_FIX="yes"
+ else
+ UDHCPC_FIX="no"
+ fi
+ export UDHCPC_FIX
+
+ if MAC1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a MAC Address(leave blank for generated MAC)" 8 58 --title "MAC ADDRESS" 3>&1 1>&2 2>&3); then
+ if [ -z "$MAC1" ]; then
+ MAC1="Default"
+ MAC=""
+ else
+ MAC=",hwaddr=$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
+ else
+ exit_script
+ fi
+
+ if VLAN1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for no VLAN)" 8 58 --title "VLAN" 3>&1 1>&2 2>&3); then
+ if [ -z "$VLAN1" ]; then
+ VLAN1="Default"
+ VLAN=""
+ else
+ VLAN=",tag=$VLAN1"
+ fi
+ echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN1${CL}"
+ else
+ exit_script
+ fi
+
+ if ADV_TAGS=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 "${TAGS}" --title "Advanced Tags" 3>&1 1>&2 2>&3); then
+ if [ -n "${ADV_TAGS}" ]; then
+ ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
+ TAGS="${ADV_TAGS}"
+ else
+ TAGS=";"
+ fi
+ echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
+ else
+ exit_script
+ fi
+
+ configure_ssh_settings
+ export SSH_KEYS_FILE
+ echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE support?\nRequired for tools like rclone, mergerfs, AppImage, etc." 10 58); then
+ ENABLE_FUSE="yes"
+ else
+ ENABLE_FUSE="no"
+ fi
+ echo -e "${FUSE}${BOLD}${DGN}Enable FUSE Support: ${BGN}$ENABLE_FUSE${CL}"
+
+ if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
+ VERBOSE="yes"
+ else
+ VERBOSE="no"
+ fi
+ echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERBOSE${CL}"
+
+ if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then
+ echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}"
+ else
+ clear
+ header_info
+ echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
+ advanced_settings
+ fi
+}
+
+# ==============================================================================
+# SECTION 7: USER INTERFACE & DIAGNOSTICS
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# diagnostics_check()
+#
+# - Ensures diagnostics config file exists at /usr/local/community-scripts/diagnostics
+# - Asks user whether to send anonymous diagnostic data
+# - Saves DIAGNOSTICS=yes/no in the config file
+# - Creates file if missing with default DIAGNOSTICS=yes
+# - Reads current diagnostics setting from file
+# - Sets global DIAGNOSTICS variable for API telemetry opt-in/out
+# ------------------------------------------------------------------------------
+diagnostics_check() {
+ if ! [ -d "/usr/local/community-scripts" ]; then
+ mkdir -p /usr/local/community-scripts
+ fi
+
+ if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then
+ if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then
+ cat </usr/local/community-scripts/diagnostics
+DIAGNOSTICS=yes
+
+#This file is used to store the diagnostics settings for the Community-Scripts API.
+#https://github.com/community-scripts/ProxmoxVED/discussions/1836
+#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
+#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
+#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
+#This will disable the diagnostics feature.
+#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
+#This will enable the diagnostics feature.
+#The following information will be sent:
+#"disk_size"
+#"core_count"
+#"ram_size"
+#"os_type"
+#"os_version"
+#"nsapp"
+#"method"
+#"pve_version"
+#"status"
+#If you have any concerns, please review the source code at /misc/build.func
+EOF
+ DIAGNOSTICS="yes"
+ else
+ cat </usr/local/community-scripts/diagnostics
+DIAGNOSTICS=no
+
+#This file is used to store the diagnostics settings for the Community-Scripts API.
+#https://github.com/community-scripts/ProxmoxVED/discussions/1836
+#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
+#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
+#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
+#This will disable the diagnostics feature.
+#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
+#This will enable the diagnostics feature.
+#The following information will be sent:
+#"disk_size"
+#"core_count"
+#"ram_size"
+#"os_type"
+#"os_version"
+#"nsapp"
+#"method"
+#"pve_version"
+#"status"
+#If you have any concerns, please review the source code at /misc/build.func
+EOF
+ DIAGNOSTICS="no"
+ fi
+ else
+ DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics)
+
+ fi
+}
+
+diagnostics_menu() {
+ if [ "${DIAGNOSTICS:-no}" = "yes" ]; then
+ if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "DIAGNOSTIC SETTINGS" \
+ --yesno "Send Diagnostics?\n\nCurrent: ${DIAGNOSTICS}" 10 58 \
+ --yes-button "No" --no-button "Back"; then
+ DIAGNOSTICS="no"
+ sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics
+ whiptail --msgbox "Diagnostics set to ${DIAGNOSTICS}." 8 58
+ fi
+ else
+ if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "DIAGNOSTIC SETTINGS" \
+ --yesno "Send Diagnostics?\n\nCurrent: ${DIAGNOSTICS}" 10 58 \
+ --yes-button "Yes" --no-button "Back"; then
+ DIAGNOSTICS="yes"
+ sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics
+ whiptail --msgbox "Diagnostics set to ${DIAGNOSTICS}." 8 58
+ fi
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# echo_default()
+#
+# - Prints summary of default values (ID, OS, type, disk, RAM, CPU, etc.)
+# - Uses icons and formatting for readability
+# - Convert CT_TYPE to description
+# ------------------------------------------------------------------------------
+echo_default() {
+ CT_TYPE_DESC="Unprivileged"
+ if [ "$CT_TYPE" -eq 0 ]; then
+ CT_TYPE_DESC="Privileged"
+ fi
+ echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CT_ID}${CL}"
+ echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os ($var_version)${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
+ if [ "$VERBOSE" == "yes" ]; then
+ echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}"
+ fi
+ echo -e "${CREATING}${BOLD}${BL}Creating a ${APP} LXC using the above default settings${CL}"
+ echo -e " "
+}
+
+# ------------------------------------------------------------------------------
+# install_script()
+#
+# - Main entrypoint for installation mode
+# - Runs safety checks (pve_check, root_check, maxkeys_check, diagnostics_check)
+# - Builds interactive menu (Default, Verbose, Advanced, My Defaults, App Defaults, Diagnostics, Storage, Exit)
+# - Applies chosen settings and triggers container build
+# ------------------------------------------------------------------------------
+install_script() {
+ pve_check
+ shell_check
+ root_check
+ arch_check
+ ssh_check
+ maxkeys_check
+ diagnostics_check
+
+ if systemctl is-active -q ping-instances.service; then
+ systemctl -q stop ping-instances.service
+ fi
+
+ NEXTID=$(pvesh get /cluster/nextid)
+ timezone=$(cat /etc/timezone)
+
+ # Show APP Header
+ header_info
+
+ # --- Support CLI argument as direct preset (default, advanced, …) ---
+ CHOICE="${mode:-${1:-}}"
+
+ # If no CLI argument → show whiptail menu
+ # Build menu dynamically based on available options
+ local appdefaults_option=""
+ local settings_option=""
+ local menu_items=(
+ "1" "Default Install"
+ "2" "Advanced Install"
+ "3" "My Defaults"
+ )
+
+ if [ -f "$(get_app_defaults_path)" ]; then
+ appdefaults_option="4"
+ menu_items+=("4" "App Defaults for ${APP}")
+ settings_option="5"
+ menu_items+=("5" "Settings")
+ else
+ settings_option="4"
+ menu_items+=("4" "Settings")
+ fi
+
+ if [ -z "$CHOICE" ]; then
+
+ TMP_CHOICE=$(whiptail \
+ --backtitle "Proxmox VE Helper Scripts" \
+ --title "Community-Scripts Options" \
+ --ok-button "Select" --cancel-button "Exit Script" \
+ --notags \
+ --menu "\nChoose an option:\n Use TAB or Arrow keys to navigate, ENTER to select.\n" \
+ 20 60 9 \
+ "${menu_items[@]}" \
+ --default-item "1" \
+ 3>&1 1>&2 2>&3) || exit_script
+ CHOICE="$TMP_CHOICE"
+ fi
+
+ APPDEFAULTS_OPTION="$appdefaults_option"
+ SETTINGS_OPTION="$settings_option"
+
+ # --- Main case ---
+ local defaults_target=""
+ local run_maybe_offer="no"
+ case "$CHOICE" in
+ 1 | default | DEFAULT)
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
+ VERBOSE="no"
+ METHOD="default"
+ base_settings "$VERBOSE"
+ echo_default
+ defaults_target="$(ensure_global_default_vars_file)"
+ ;;
+ 2 | advanced | ADVANCED)
+ header_info
+
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Install on node $PVEHOST_NAME${CL}"
+ echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
+ METHOD="advanced"
+ base_settings
+ advanced_settings
+ defaults_target="$(ensure_global_default_vars_file)"
+ run_maybe_offer="yes"
+ ;;
+ 3 | mydefaults | MYDEFAULTS)
+ default_var_settings || {
+ msg_error "Failed to apply default.vars"
+ exit 1
+ }
+ defaults_target="/usr/local/community-scripts/default.vars"
+ ;;
+ "$APPDEFAULTS_OPTION" | appdefaults | APPDEFAULTS)
+ if [ -f "$(get_app_defaults_path)" ]; then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using App Defaults for ${APP} on node $PVEHOST_NAME${CL}"
+ METHOD="appdefaults"
+ base_settings
+ _load_vars_file "$(get_app_defaults_path)"
+ echo_default
+ defaults_target="$(get_app_defaults_path)"
+ else
+ msg_error "No App Defaults available for ${APP}"
+ exit 1
+ fi
+ ;;
+ "$SETTINGS_OPTION" | settings | SETTINGS)
+ settings_menu
+ defaults_target=""
+ ;;
+ *)
+ echo -e "${CROSS}${RD}Invalid option: $CHOICE${CL}"
+ exit 1
+ ;;
+ esac
+
+ if [[ -n "$defaults_target" ]]; then
+ ensure_storage_selection_for_vars_file "$defaults_target"
+ fi
+
+ if [[ "$run_maybe_offer" == "yes" ]]; then
+ maybe_offer_save_app_defaults
+ fi
+}
+
+edit_default_storage() {
+ local vf="/usr/local/community-scripts/default.vars"
+
+ # Ensure file exists
+ if [[ ! -f "$vf" ]]; then
+ mkdir -p "$(dirname "$vf")"
+ touch "$vf"
+ fi
+
+ # Let ensure_storage_selection_for_vars_file handle everything
+ ensure_storage_selection_for_vars_file "$vf"
+}
+
+settings_menu() {
+ while true; do
+ local settings_items=(
+ "1" "Manage API-Diagnostic Setting"
+ "2" "Edit Default.vars"
+ "3" "Edit Default Storage"
+ )
+ if [ -f "$(get_app_defaults_path)" ]; then
+ settings_items+=("4" "Edit App.vars for ${APP}")
+ settings_items+=("5" "Exit")
+ else
+ settings_items+=("4" "Exit")
+ fi
+
+ local choice
+ choice=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
+ --title "Community-Scripts SETTINGS Menu" \
+ --ok-button "OK" --cancel-button "Back" \
+ --menu "\n\nChoose a settings option:\n\nUse TAB or Arrow keys to navigate, ENTER to select." 20 60 9 \
+ "${settings_items[@]}" \
+ 3>&1 1>&2 2>&3) || break
+
+ case "$choice" in
+ 1) diagnostics_menu ;;
+ 2) ${EDITOR:-nano} /usr/local/community-scripts/default.vars ;;
+ 3) edit_default_storage ;;
+ 4)
+ if [ -f "$(get_app_defaults_path)" ]; then
+ ${EDITOR:-nano} "$(get_app_defaults_path)"
+ else
+ exit_script
+ fi
+ ;;
+ 5) exit_script ;;
+ esac
+ done
+}
+
+# ------------------------------------------------------------------------------
+# check_container_resources()
+#
+# - Compares host RAM/CPU with required values
+# - Warns if under-provisioned and asks user to continue or abort
+# ------------------------------------------------------------------------------
+check_container_resources() {
+ current_ram=$(free -m | awk 'NR==2{print $2}')
+ current_cpu=$(nproc)
+
+ if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then
+ echo -e "\n${INFO}${HOLD} ${GN}Required: ${var_cpu} CPU, ${var_ram}MB RAM ${CL}| ${RD}Current: ${current_cpu} CPU, ${current_ram}MB RAM${CL}"
+ echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n"
+ echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? "
+ read -r prompt
+ if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then
+ echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}"
+ exit 1
+ fi
+ else
+ echo -e ""
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# check_container_storage()
+#
+# - Checks /boot partition usage
+# - Warns if usage >80% and asks user confirmation before proceeding
+# ------------------------------------------------------------------------------
+check_container_storage() {
+ total_size=$(df /boot --output=size | tail -n 1)
+ local used_size=$(df /boot --output=used | tail -n 1)
+ usage=$((100 * used_size / total_size))
+ if ((usage > 80)); then
+ echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}"
+ echo -ne "Continue anyway? "
+ read -r prompt
+ if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then
+ echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}"
+ exit 1
+ fi
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# ssh_extract_keys_from_file()
+#
+# - Extracts valid SSH public keys from given file
+# - Supports RSA, Ed25519, ECDSA and filters out comments/invalid lines
+# ------------------------------------------------------------------------------
+ssh_extract_keys_from_file() {
+ local f="$1"
+ [[ -r "$f" ]] || return 0
+ tr -d '\r' <"$f" | awk '
+ /^[[:space:]]*#/ {next}
+ /^[[:space:]]*$/ {next}
+ # nackt: typ base64 [comment]
+ /^(ssh-(rsa|ed25519)|ecdsa-sha2-nistp256|sk-(ssh-ed25519|ecdsa-sha2-nistp256))[[:space:]]+/ {print; next}
+ # mit Optionen: finde ab erstem Key-Typ
+ {
+ match($0, /(ssh-(rsa|ed25519)|ecdsa-sha2-nistp256|sk-(ssh-ed25519|ecdsa-sha2-nistp256))[[:space:]]+/)
+ if (RSTART>0) { print substr($0, RSTART) }
+ }
+ '
+}
+
+# ------------------------------------------------------------------------------
+# ssh_build_choices_from_files()
+#
+# - Builds interactive whiptail checklist of available SSH keys
+# - Generates fingerprint, type and comment for each key
+# ------------------------------------------------------------------------------
+ssh_build_choices_from_files() {
+ local -a files=("$@")
+ CHOICES=()
+ COUNT=0
+ MAPFILE="$(mktemp)"
+ local id key typ fp cmt base ln=0
+
+ for f in "${files[@]}"; do
+ [[ -f "$f" && -r "$f" ]] || continue
+ base="$(basename -- "$f")"
+ case "$base" in
+ known_hosts | known_hosts.* | config) continue ;;
+ id_*) [[ "$f" != *.pub ]] && continue ;;
+ esac
+
+ # map every key in file
+ while IFS= read -r key; do
+ [[ -n "$key" ]] || continue
+
+ typ=""
+ fp=""
+ cmt=""
+ # Only the pure key part (without options) is already included in ‘key’.
+ read -r _typ _b64 _cmt <<<"$key"
+ typ="${_typ:-key}"
+ cmt="${_cmt:-}"
+ # Fingerprint via ssh-keygen (if available)
+ if command -v ssh-keygen >/dev/null 2>&1; then
+ fp="$(printf '%s\n' "$key" | ssh-keygen -lf - 2>/dev/null | awk '{print $2}')"
+ fi
+ # Label shorten
+ [[ ${#cmt} -gt 40 ]] && cmt="${cmt:0:37}..."
+
+ ln=$((ln + 1))
+ COUNT=$((COUNT + 1))
+ id="K${COUNT}"
+ echo "${id}|${key}" >>"$MAPFILE"
+ CHOICES+=("$id" "[$typ] ${fp:+$fp }${cmt:+$cmt }— ${base}" "OFF")
+ done < <(ssh_extract_keys_from_file "$f")
+ done
+}
+
+# ------------------------------------------------------------------------------
+# ssh_discover_default_files()
+#
+# - Scans standard paths for SSH keys
+# - Includes ~/.ssh/*.pub, /etc/ssh/authorized_keys, etc.
+# ------------------------------------------------------------------------------
+ssh_discover_default_files() {
+ local -a cand=()
+ shopt -s nullglob
+ cand+=(/root/.ssh/authorized_keys /root/.ssh/authorized_keys2)
+ cand+=(/root/.ssh/*.pub)
+ cand+=(/etc/ssh/authorized_keys /etc/ssh/authorized_keys.d/*)
+ shopt -u nullglob
+ printf '%s\0' "${cand[@]}"
+}
+
+configure_ssh_settings() {
+ SSH_KEYS_FILE="$(mktemp)"
+ : >"$SSH_KEYS_FILE"
+
+ IFS=$'\0' read -r -d '' -a _def_files < <(ssh_discover_default_files && printf '\0')
+ ssh_build_choices_from_files "${_def_files[@]}"
+ local default_key_count="$COUNT"
+
+ local ssh_key_mode
+ if [[ "$default_key_count" -gt 0 ]]; then
+ ssh_key_mode=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SSH KEY SOURCE" --menu \
+ "Provision SSH keys for root:" 14 72 4 \
+ "found" "Select from detected keys (${default_key_count})" \
+ "manual" "Paste a single public key" \
+ "folder" "Scan another folder (path or glob)" \
+ "none" "No keys" 3>&1 1>&2 2>&3) || exit_script
+ else
+ ssh_key_mode=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SSH KEY SOURCE" --menu \
+ "No host keys detected; choose manual/none:" 12 72 2 \
+ "manual" "Paste a single public key" \
+ "none" "No keys" 3>&1 1>&2 2>&3) || exit_script
+ fi
+
+ case "$ssh_key_mode" in
+ found)
+ local selection
+ selection=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SELECT HOST KEYS" \
+ --checklist "Select one or more keys to import:" 20 140 10 "${CHOICES[@]}" 3>&1 1>&2 2>&3) || exit_script
+ for tag in $selection; do
+ tag="${tag%\"}"
+ tag="${tag#\"}"
+ local line
+ line=$(grep -E "^${tag}\|" "$MAPFILE" | head -n1 | cut -d'|' -f2-)
+ [[ -n "$line" ]] && printf '%s\n' "$line" >>"$SSH_KEYS_FILE"
+ done
+ ;;
+ manual)
+ SSH_AUTHORIZED_KEY="$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --inputbox "Paste one SSH public key line (ssh-ed25519/ssh-rsa/...)" 10 72 --title "SSH Public Key" 3>&1 1>&2 2>&3)"
+ [[ -n "$SSH_AUTHORIZED_KEY" ]] && printf '%s\n' "$SSH_AUTHORIZED_KEY" >>"$SSH_KEYS_FILE"
+ ;;
+ folder)
+ local glob_path
+ glob_path=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --inputbox "Enter a folder or glob to scan (e.g. /root/.ssh/*.pub)" 10 72 --title "Scan Folder/Glob" 3>&1 1>&2 2>&3)
+ if [[ -n "$glob_path" ]]; then
+ shopt -s nullglob
+ read -r -a _scan_files <<<"$glob_path"
+ shopt -u nullglob
+ if [[ "${#_scan_files[@]}" -gt 0 ]]; then
+ ssh_build_choices_from_files "${_scan_files[@]}"
+ if [[ "$COUNT" -gt 0 ]]; then
+ local folder_selection
+ folder_selection=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SELECT FOLDER KEYS" \
+ --checklist "Select key(s) to import:" 20 78 10 "${CHOICES[@]}" 3>&1 1>&2 2>&3) || exit_script
+ for tag in $folder_selection; do
+ tag="${tag%\"}"
+ tag="${tag#\"}"
+ local line
+ line=$(grep -E "^${tag}\|" "$MAPFILE" | head -n1 | cut -d'|' -f2-)
+ [[ -n "$line" ]] && printf '%s\n' "$line" >>"$SSH_KEYS_FILE"
+ done
+ else
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "No keys found in: $glob_path" 8 60
+ fi
+ else
+ whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "Path/glob returned no files." 8 60
+ fi
+ fi
+ ;;
+ none)
+ :
+ ;;
+ esac
+
+ if [[ -s "$SSH_KEYS_FILE" ]]; then
+ sort -u -o "$SSH_KEYS_FILE" "$SSH_KEYS_FILE"
+ printf '\n' >>"$SSH_KEYS_FILE"
+ fi
+
+ if [[ -s "$SSH_KEYS_FILE" || "$PW" == -password* ]]; then
+ if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable root SSH access?" 10 58); then
+ SSH="yes"
+ else
+ SSH="no"
+ fi
+ else
+ SSH="no"
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# start()
+#
+# - Entry point of script
+# - On Proxmox host: calls install_script
+# - In silent mode: runs update_script
+# - Otherwise: shows update/setting menu
+# ------------------------------------------------------------------------------
+start() {
+ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/tools.func)
+ if command -v pveversion >/dev/null 2>&1; then
+ install_script || return 0
+ return 0
+ elif [ ! -z ${PHS_SILENT+x} ] && [[ "${PHS_SILENT}" == "1" ]]; then
+ VERBOSE="no"
+ set_std_mode
+ update_script
+ else
+ CHOICE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \
+ "Support/Update functions for ${APP} LXC. Choose an option:" \
+ 12 60 3 \
+ "1" "YES (Silent Mode)" \
+ "2" "YES (Verbose Mode)" \
+ "3" "NO (Cancel Update)" --nocancel --default-item "1" 3>&1 1>&2 2>&3)
+
+ case "$CHOICE" in
+ 1)
+ VERBOSE="no"
+ set_std_mode
+ ;;
+ 2)
+ VERBOSE="yes"
+ set_std_mode
+ ;;
+ 3)
+ clear
+ exit_script
+ exit
+ ;;
+ esac
+ update_script
+ fi
+}
+
+# ==============================================================================
+# SECTION 8: CONTAINER CREATION & DEPLOYMENT
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# build_container()
+#
+# - Main function for creating and configuring LXC container
+# - Builds network configuration string (IP, gateway, VLAN, MTU, MAC, IPv6)
+# - Creates container via pct create with all specified settings
+# - Applies features: FUSE, TUN, keyctl, VAAPI passthrough
+# - Starts container and waits for network connectivity
+# - Installs base packages (curl, sudo, etc.)
+# - Injects SSH keys if configured
+# - Executes -install.sh inside container
+# - Posts installation telemetry to API if diagnostics enabled
+# ------------------------------------------------------------------------------
+build_container() {
+ # if [ "$VERBOSE" == "yes" ]; then set -x; fi
+
+ NET_STRING="-net0 name=eth0,bridge=${BRG:-vmbr0}"
+
+ # MAC
+ if [[ -n "$MAC" ]]; then
+ case "$MAC" in
+ ,hwaddr=*) NET_STRING+="$MAC" ;;
+ *) NET_STRING+=",hwaddr=$MAC" ;;
+ esac
+ fi
+
+ # IP (immer zwingend, Standard dhcp)
+ NET_STRING+=",ip=${NET:-dhcp}"
+
+ # Gateway
+ if [[ -n "$GATE" ]]; then
+ case "$GATE" in
+ ,gw=*) NET_STRING+="$GATE" ;;
+ *) NET_STRING+=",gw=$GATE" ;;
+ esac
+ fi
+
+ # VLAN
+ if [[ -n "$VLAN" ]]; then
+ case "$VLAN" in
+ ,tag=*) NET_STRING+="$VLAN" ;;
+ *) NET_STRING+=",tag=$VLAN" ;;
+ esac
+ fi
+
+ # MTU
+ if [[ -n "$MTU" ]]; then
+ case "$MTU" in
+ ,mtu=*) NET_STRING+="$MTU" ;;
+ *) NET_STRING+=",mtu=$MTU" ;;
+ esac
+ fi
+
+ # IPv6 Handling
+ case "$IPV6_METHOD" in
+ auto) NET_STRING="$NET_STRING,ip6=auto" ;;
+ dhcp) NET_STRING="$NET_STRING,ip6=dhcp" ;;
+ static)
+ NET_STRING="$NET_STRING,ip6=$IPV6_ADDR"
+ [ -n "$IPV6_GATE" ] && NET_STRING="$NET_STRING,gw6=$IPV6_GATE"
+ ;;
+ none) ;;
+ esac
+
+ if [ "$CT_TYPE" == "1" ]; then
+ FEATURES="keyctl=1,nesting=1"
+ else
+ FEATURES="nesting=1"
+ fi
+
+ if [ "$ENABLE_FUSE" == "yes" ]; then
+ FEATURES="$FEATURES,fuse=1"
+ fi
+
+ TEMP_DIR=$(mktemp -d)
+ pushd "$TEMP_DIR" >/dev/null
+ if [ "$var_os" == "alpine" ]; then
+ export FUNCTIONS_FILE_PATH="$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/alpine-install.func)"
+ else
+ export FUNCTIONS_FILE_PATH="$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/install.func)"
+ fi
+ export DIAGNOSTICS="$DIAGNOSTICS"
+ export RANDOM_UUID="$RANDOM_UUID"
+ export SESSION_ID="$SESSION_ID"
+ export CACHER="$APT_CACHER"
+ export CACHER_IP="$APT_CACHER_IP"
+ export tz="$timezone"
+ export APPLICATION="$APP"
+ export app="$NSAPP"
+ export PASSWORD="$PW"
+ export VERBOSE="$VERBOSE"
+ export SSH_ROOT="${SSH}"
+ export SSH_AUTHORIZED_KEY
+ export CTID="$CT_ID"
+ export CTTYPE="$CT_TYPE"
+ export ENABLE_FUSE="$ENABLE_FUSE"
+ export ENABLE_TUN="$ENABLE_TUN"
+ export PCT_OSTYPE="$var_os"
+ export PCT_OSVERSION="$var_version"
+ export PCT_DISK_SIZE="$DISK_SIZE"
+ export PCT_OPTIONS="
+ -features $FEATURES
+ -hostname $HN
+ -tags $TAGS
+ $SD
+ $NS
+ $NET_STRING
+ -onboot 1
+ -cores $CORE_COUNT
+ -memory $RAM_SIZE
+ -unprivileged $CT_TYPE
+ $PW
+"
+ export TEMPLATE_STORAGE="${var_template_storage:-}"
+ export CONTAINER_STORAGE="${var_container_storage:-}"
+ create_lxc_container || exit $?
+
+ LXC_CONFIG="/etc/pve/lxc/${CTID}.conf"
+
+ # ============================================================================
+ # GPU/USB PASSTHROUGH CONFIGURATION
+ # ============================================================================
+
+ # List of applications that benefit from GPU acceleration
+ GPU_APPS=(
+ "immich" "channels" "emby" "ersatztv" "frigate"
+ "jellyfin" "plex" "scrypted" "tdarr" "unmanic"
+ "ollama" "fileflows" "open-webui" "tunarr" "debian"
+ "handbrake" "sunshine" "moonlight" "kodi" "stremio"
+ "viseron"
+ )
+
+ # Check if app needs GPU
+ is_gpu_app() {
+ local app="${1,,}"
+ for gpu_app in "${GPU_APPS[@]}"; do
+ [[ "$app" == "${gpu_app,,}" ]] && return 0
+ done
+ return 1
+ }
+
+ # Detect all available GPU devices
+ detect_gpu_devices() {
+ INTEL_DEVICES=()
+ AMD_DEVICES=()
+ NVIDIA_DEVICES=()
+
+ # Store PCI info to avoid multiple calls
+ local pci_vga_info=$(lspci -nn 2>/dev/null | grep -E "VGA|Display|3D")
+
+ # Check for Intel GPU - look for Intel vendor ID [8086]
+ if echo "$pci_vga_info" | grep -q "\[8086:"; then
+ msg_custom "🎮" "${BL}" "Detected Intel GPU"
+ if [[ -d /dev/dri ]]; then
+ for d in /dev/dri/renderD* /dev/dri/card*; do
+ [[ -e "$d" ]] && INTEL_DEVICES+=("$d")
+ done
+ fi
+ fi
+
+ # Check for AMD GPU - look for AMD vendor IDs [1002] (AMD/ATI) or [1022] (AMD)
+ if echo "$pci_vga_info" | grep -qE "\[1002:|\[1022:"; then
+ msg_custom "🎮" "${RD}" "Detected AMD GPU"
+ if [[ -d /dev/dri ]]; then
+ # Only add if not already claimed by Intel
+ if [[ ${#INTEL_DEVICES[@]} -eq 0 ]]; then
+ for d in /dev/dri/renderD* /dev/dri/card*; do
+ [[ -e "$d" ]] && AMD_DEVICES+=("$d")
+ done
+ fi
+ fi
+ fi
+
+ # Check for NVIDIA GPU - look for NVIDIA vendor ID [10de]
+ if echo "$pci_vga_info" | grep -q "\[10de:"; then
+ msg_custom "🎮" "${GN}" "Detected NVIDIA GPU"
+
+ # Simple passthrough - just bind /dev/nvidia* devices if they exist
+ for d in /dev/nvidia* /dev/nvidiactl /dev/nvidia-modeset /dev/nvidia-uvm /dev/nvidia-uvm-tools; do
+ [[ -e "$d" ]] && NVIDIA_DEVICES+=("$d")
+ done
+
+ if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
+ msg_custom "🎮" "${GN}" "Found ${#NVIDIA_DEVICES[@]} NVIDIA device(s) for passthrough"
+ else
+ msg_warn "NVIDIA GPU detected via PCI but no /dev/nvidia* devices found"
+ msg_custom "ℹ️" "${YW}" "Skipping NVIDIA passthrough (host drivers may not be loaded)"
+ fi
+ fi
+
+ # Debug output
+ msg_debug "Intel devices: ${INTEL_DEVICES[*]}"
+ msg_debug "AMD devices: ${AMD_DEVICES[*]}"
+ msg_debug "NVIDIA devices: ${NVIDIA_DEVICES[*]}"
+ }
+
+ # Configure USB passthrough for privileged containers
+ configure_usb_passthrough() {
+ if [[ "$CT_TYPE" != "0" ]]; then
+ return 0
+ fi
+
+ msg_info "Configuring automatic USB passthrough (privileged container)"
+ cat <>"$LXC_CONFIG"
+# Automatic USB passthrough (privileged container)
+lxc.cgroup2.devices.allow: a
+lxc.cap.drop:
+lxc.cgroup2.devices.allow: c 188:* rwm
+lxc.cgroup2.devices.allow: c 189:* rwm
+lxc.mount.entry: /dev/serial/by-id dev/serial/by-id none bind,optional,create=dir
+lxc.mount.entry: /dev/ttyUSB0 dev/ttyUSB0 none bind,optional,create=file
+lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create=file
+lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file
+lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file
+EOF
+ msg_ok "USB passthrough configured"
+ }
+
+ # Configure GPU passthrough
+ configure_gpu_passthrough() {
+ # Skip if not a GPU app and not privileged
+ if [[ "$CT_TYPE" != "0" ]] && ! is_gpu_app "$APP"; then
+ return 0
+ fi
+
+ detect_gpu_devices
+
+ # Count available GPU types
+ local gpu_count=0
+ local available_gpus=()
+
+ if [[ ${#INTEL_DEVICES[@]} -gt 0 ]]; then
+ available_gpus+=("INTEL")
+ gpu_count=$((gpu_count + 1))
+ fi
+
+ if [[ ${#AMD_DEVICES[@]} -gt 0 ]]; then
+ available_gpus+=("AMD")
+ gpu_count=$((gpu_count + 1))
+ fi
+
+ if [[ ${#NVIDIA_DEVICES[@]} -gt 0 ]]; then
+ available_gpus+=("NVIDIA")
+ gpu_count=$((gpu_count + 1))
+ fi
+
+ if [[ $gpu_count -eq 0 ]]; then
+ msg_custom "ℹ️" "${YW}" "No GPU devices found for passthrough"
+ return 0
+ fi
+
+ local selected_gpu=""
+
+ if [[ $gpu_count -eq 1 ]]; then
+ # Automatic selection for single GPU
+ selected_gpu="${available_gpus[0]}"
+ msg_custom "⚙️" "${GN}" "Automatically configuring ${selected_gpu} GPU passthrough"
+ else
+ # Multiple GPUs - ask user
+ echo -e "\n${INFO} Multiple GPU types detected:"
+ for gpu in "${available_gpus[@]}"; do
+ echo " - $gpu"
+ done
+ read -rp "Which GPU type to passthrough? (${available_gpus[*]}): " selected_gpu
+ selected_gpu="${selected_gpu^^}"
+
+ # Validate selection
+ local valid=0
+ for gpu in "${available_gpus[@]}"; do
+ [[ "$selected_gpu" == "$gpu" ]] && valid=1
+ done
+
+ if [[ $valid -eq 0 ]]; then
+ msg_warn "Invalid selection. Skipping GPU passthrough."
+ return 0
+ fi
+ fi
+
+ # Apply passthrough configuration based on selection
+ local dev_idx=0
+
+ case "$selected_gpu" in
+ INTEL | AMD)
+ local devices=()
+ [[ "$selected_gpu" == "INTEL" ]] && devices=("${INTEL_DEVICES[@]}")
+ [[ "$selected_gpu" == "AMD" ]] && devices=("${AMD_DEVICES[@]}")
+
+ # Add lxc.mount.entry for each device
+ for dev in "${devices[@]}"; do
+ echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
+
+ if [[ "$CT_TYPE" == "0" ]]; then
+ # Privileged container - also add cgroup allows
+ local major minor
+ major=$(stat -c '%t' "$dev" 2>/dev/null || echo "0")
+ minor=$(stat -c '%T' "$dev" 2>/dev/null || echo "0")
+
+ if [[ "$major" != "0" && "$minor" != "0" ]]; then
+ echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG"
+ fi
+ fi
+ done
+
+ export GPU_TYPE="$selected_gpu"
+ msg_ok "${selected_gpu} GPU passthrough configured (${#devices[@]} devices)"
+ ;;
+
+ NVIDIA)
+ if [[ ${#NVIDIA_DEVICES[@]} -eq 0 ]]; then
+ msg_warn "No NVIDIA devices available for passthrough"
+ return 0
+ fi
+
+ # Add lxc.mount.entry for each NVIDIA device
+ for dev in "${NVIDIA_DEVICES[@]}"; do
+ echo "lxc.mount.entry: $dev $dev none bind,optional,create=file" >>"$LXC_CONFIG"
+
+ if [[ "$CT_TYPE" == "0" ]]; then
+ # Privileged container - also add cgroup allows
+ local major minor
+ major=$(stat -c '%t' "$dev" 2>/dev/null || echo "0")
+ minor=$(stat -c '%T' "$dev" 2>/dev/null || echo "0")
+
+ if [[ "$major" != "0" && "$minor" != "0" ]]; then
+ echo "lxc.cgroup2.devices.allow: c $((0x$major)):$((0x$minor)) rwm" >>"$LXC_CONFIG"
+ fi
+ fi
+ done
+
+ export GPU_TYPE="NVIDIA"
+ msg_ok "NVIDIA GPU passthrough configured (${#NVIDIA_DEVICES[@]} devices) - install drivers in container if needed"
+ ;;
+ esac
+ }
+
+ # Additional device passthrough
+ configure_additional_devices() {
+ # TUN device passthrough
+ if [ "$ENABLE_TUN" == "yes" ]; then
+ cat <>"$LXC_CONFIG"
+lxc.cgroup2.devices.allow: c 10:200 rwm
+lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
+EOF
+ fi
+
+ # Coral TPU passthrough
+ if [[ -e /dev/apex_0 ]]; then
+ msg_custom "🔌" "${BL}" "Detected Coral TPU - configuring passthrough"
+ echo "lxc.mount.entry: /dev/apex_0 dev/apex_0 none bind,optional,create=file" >>"$LXC_CONFIG"
+ fi
+ }
+
+ # Execute pre-start configurations
+ configure_usb_passthrough
+ configure_gpu_passthrough
+ configure_additional_devices
+
+ # ============================================================================
+ # START CONTAINER AND INSTALL USERLAND
+ # ============================================================================
+
+ msg_info "Starting LXC Container"
+ pct start "$CTID"
+
+ # Wait for container to be running
+ for i in {1..10}; do
+ if pct status "$CTID" | grep -q "status: running"; then
+ msg_ok "Started LXC Container"
+ break
+ fi
+ sleep 1
+ if [ "$i" -eq 10 ]; then
+ msg_error "LXC Container did not reach running state"
+ exit 1
+ fi
+ done
+
+ # Wait for network (skip for Alpine initially)
+ if [ "$var_os" != "alpine" ]; then
+ msg_info "Waiting for network in LXC container"
+
+ # Wait for IP
+ for i in {1..20}; do
+ ip_in_lxc=$(pct exec "$CTID" -- ip -4 addr show dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
+ [ -n "$ip_in_lxc" ] && break
+ sleep 1
+ done
+
+ if [ -z "$ip_in_lxc" ]; then
+ msg_error "No IP assigned to CT $CTID after 20s"
+ exit 1
+ fi
+
+ # Simple connectivity check - just verify IP is assigned
+ msg_ok "Network configured (IP: $ip_in_lxc)"
+ fi
+ # Function to get correct GID inside container
+ get_container_gid() {
+ local group="$1"
+ local gid=$(pct exec "$CTID" -- getent group "$group" 2>/dev/null | cut -d: -f3)
+ echo "${gid:-44}" # Default to 44 if not found
+ }
+
+ fix_gpu_gids
+
+ # Continue with standard container setup
+ msg_info "Customizing LXC Container"
+
+ # # Install GPU userland if configured
+ # if [[ "${ENABLE_VAAPI:-0}" == "1" ]]; then
+ # install_gpu_userland "VAAPI"
+ # fi
+
+ # if [[ "${ENABLE_NVIDIA:-0}" == "1" ]]; then
+ # install_gpu_userland "NVIDIA"
+ # fi
+
+ # Continue with standard container setup
+ if [ "$var_os" == "alpine" ]; then
+ sleep 3
+ pct exec "$CTID" -- /bin/sh -c 'cat </etc/apk/repositories
+http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
+http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
+EOF'
+ pct exec "$CTID" -- ash -c "apk add bash newt curl openssh nano mc ncurses jq >/dev/null"
+ else
+ sleep 3
+ pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen"
+ pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
+ echo LANG=\$locale_line >/etc/default/locale && \
+ locale-gen >/dev/null && \
+ export LANG=\$locale_line"
+
+ if [[ -z "${tz:-}" ]]; then
+ tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "Etc/UTC")
+ fi
+
+ if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
+ pct exec "$CTID" -- bash -c "tz='$tz'; echo \"\$tz\" >/etc/timezone && ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime"
+ else
+ msg_warn "Skipping timezone setup – zone '$tz' not found in container"
+ fi
+
+ pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y sudo curl mc gnupg2 jq >/dev/null" || {
+ msg_error "apt-get base packages installation failed"
+ exit 1
+ }
+ fi
+
+ msg_ok "Customized LXC Container"
+
+ # Install SSH keys
+ install_ssh_keys_into_ct
+
+ # Run application installer
+ if ! lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)"; then
+ local exit_code=$?
+ # Try to copy installation log from container before exiting
+ if [[ -n "$CTID" && -n "${SESSION_ID:-}" ]]; then
+ pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "/tmp/install-${SESSION_ID}.log" 2>/dev/null || true
+ fi
+ exit $exit_code
+ fi
+}
+
+destroy_lxc() {
+ if [[ -z "$CT_ID" ]]; then
+ msg_error "No CT_ID found. Nothing to remove."
+ return 1
+ fi
+
+ # Abbruch bei Ctrl-C / Ctrl-D / ESC
+ trap 'echo; msg_error "Aborted by user (SIGINT/SIGQUIT)"; return 130' INT QUIT
+
+ local prompt
+ if ! read -rp "Remove this Container? " prompt; then
+ # read gibt != 0 zurück bei Ctrl-D/ESC
+ msg_error "Aborted input (Ctrl-D/ESC)"
+ return 130
+ fi
+
+ case "${prompt,,}" in
+ y | yes)
+ if pct stop "$CT_ID" &>/dev/null && pct destroy "$CT_ID" &>/dev/null; then
+ msg_ok "Removed Container $CT_ID"
+ else
+ msg_error "Failed to remove Container $CT_ID"
+ return 1
+ fi
+ ;;
+ "" | n | no)
+ msg_custom "ℹ️" "${BL}" "Container was not removed."
+ ;;
+ *)
+ msg_warn "Invalid response. Container was not removed."
+ ;;
+ esac
+}
+
+# ------------------------------------------------------------------------------
+# Storage discovery / selection helpers
+# ------------------------------------------------------------------------------
+# ===== Storage discovery / selection helpers (ported from create_lxc.sh) =====
+resolve_storage_preselect() {
+ local class="$1" preselect="$2" required_content=""
+ case "$class" in
+ template) required_content="vztmpl" ;;
+ container) required_content="rootdir" ;;
+ *) return 1 ;;
+ esac
+ [[ -z "$preselect" ]] && return 1
+ if ! pvesm status -content "$required_content" | awk 'NR>1{print $1}' | grep -qx -- "$preselect"; then
+ msg_warn "Preselected storage '${preselect}' does not support content '${required_content}' (or not found)"
+ return 1
+ fi
+
+ local line total used free
+ line="$(pvesm status | awk -v s="$preselect" 'NR>1 && $1==s {print $0}')"
+ if [[ -z "$line" ]]; then
+ STORAGE_INFO="n/a"
+ else
+ total="$(awk '{print $4}' <<<"$line")"
+ used="$(awk '{print $5}' <<<"$line")"
+ free="$(awk '{print $6}' <<<"$line")"
+ local total_h used_h free_h
+ if command -v numfmt >/dev/null 2>&1; then
+ total_h="$(numfmt --to=iec --suffix=B --format %.1f "$total" 2>/dev/null || echo "$total")"
+ used_h="$(numfmt --to=iec --suffix=B --format %.1f "$used" 2>/dev/null || echo "$used")"
+ free_h="$(numfmt --to=iec --suffix=B --format %.1f "$free" 2>/dev/null || echo "$free")"
+ STORAGE_INFO="Free: ${free_h} Used: ${used_h}"
+ else
+ STORAGE_INFO="Free: ${free} Used: ${used}"
+ fi
+ fi
+ STORAGE_RESULT="$preselect"
+ return 0
+}
+
+fix_gpu_gids() {
+ if [[ -z "${GPU_TYPE:-}" ]]; then
+ return 0
+ fi
+
+ # Silent operation to avoid spinner conflicts
+ msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs"
+
+ # Ermittle die tatsächlichen GIDs aus dem Container
+ local video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3")
+ local render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3")
+
+ # Fallbacks wenn Gruppen nicht existieren
+ if [[ -z "$video_gid" ]]; then
+ # Versuche die video Gruppe zu erstellen
+ pct exec "$CTID" -- sh -c "groupadd -r video 2>/dev/null || true"
+ video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3")
+ [[ -z "$video_gid" ]] && video_gid="44" # Ultimate fallback
+ fi
+
+ if [[ -z "$render_gid" ]]; then
+ # Versuche die render Gruppe zu erstellen
+ pct exec "$CTID" -- sh -c "groupadd -r render 2>/dev/null || true"
+ render_gid=$(pct exec "$CTID" -- sh -c "getent group render 2>/dev/null | cut -d: -f3")
+ [[ -z "$render_gid" ]] && render_gid="104" # Ultimate fallback
+ fi
+
+ msg_custom "ℹ️" "${DGN}" "Container GIDs detected - video:${video_gid}, render:${render_gid}"
+
+ # Prüfe ob die GIDs von den Defaults abweichen
+ local need_update=0
+ if [[ "$video_gid" != "44" ]] || [[ "$render_gid" != "104" ]]; then
+ need_update=1
+ fi
+
+ if [[ $need_update -eq 1 ]]; then
+ msg_custom "🔄" "${YW}" "Updating device GIDs in container config"
+
+ # Stoppe Container für Config-Update
+ pct stop "$CTID" >/dev/null 2>&1
+
+ # Update die dev Einträge mit korrekten GIDs
+ # Backup der Config
+ cp "$LXC_CONFIG" "${LXC_CONFIG}.bak"
+
+ # Parse und update jeden dev Eintrag
+ while IFS= read -r line; do
+ if [[ "$line" =~ ^dev[0-9]+: ]]; then
+ # Extract device path
+ local device_path=$(echo "$line" | sed -E 's/^dev[0-9]+: ([^,]+).*/\1/')
+ local dev_num=$(echo "$line" | sed -E 's/^(dev[0-9]+):.*/\1/')
+
+ if [[ "$device_path" =~ renderD ]]; then
+ # RenderD device - use render GID
+ echo "${dev_num}: ${device_path},gid=${render_gid}"
+ elif [[ "$device_path" =~ card ]]; then
+ # Card device - use video GID
+ echo "${dev_num}: ${device_path},gid=${video_gid}"
+ else
+ # Keep original line
+ echo "$line"
+ fi
+ else
+ # Keep non-dev lines
+ echo "$line"
+ fi
+ done <"$LXC_CONFIG" >"${LXC_CONFIG}.new"
+
+ mv "${LXC_CONFIG}.new" "$LXC_CONFIG"
+
+ # Starte Container wieder
+ pct start "$CTID" >/dev/null 2>&1
+ sleep 3
+
+ msg_ok "Device GIDs updated successfully"
+ else
+ msg_ok "Device GIDs are already correct"
+ fi
+ if [[ "$CT_TYPE" == "0" ]]; then
+ pct exec "$CTID" -- bash -c "
+ if [ -d /dev/dri ]; then
+ for dev in /dev/dri/*; do
+ if [ -e \"\$dev\" ]; then
+ if [[ \"\$dev\" =~ renderD ]]; then
+ chgrp ${render_gid} \"\$dev\" 2>/dev/null || true
+ else
+ chgrp ${video_gid} \"\$dev\" 2>/dev/null || true
+ fi
+ chmod 660 \"\$dev\" 2>/dev/null || true
+ fi
+ done
+ fi
+ " >/dev/null 2>&1
+ fi
+}
+
+check_storage_support() {
+ local CONTENT="$1" VALID=0
+ while IFS= read -r line; do
+ local STORAGE_NAME
+ STORAGE_NAME=$(awk '{print $1}' <<<"$line")
+ [[ -n "$STORAGE_NAME" ]] && VALID=1
+ done < <(pvesm status -content "$CONTENT" 2>/dev/null | awk 'NR>1')
+ [[ $VALID -eq 1 ]]
+}
+
+select_storage() {
+ local CLASS=$1 CONTENT CONTENT_LABEL
+ case $CLASS in
+ container)
+ CONTENT='rootdir'
+ CONTENT_LABEL='Container'
+ ;;
+ template)
+ CONTENT='vztmpl'
+ CONTENT_LABEL='Container template'
+ ;;
+ iso)
+ CONTENT='iso'
+ CONTENT_LABEL='ISO image'
+ ;;
+ images)
+ CONTENT='images'
+ CONTENT_LABEL='VM Disk image'
+ ;;
+ backup)
+ CONTENT='backup'
+ CONTENT_LABEL='Backup'
+ ;;
+ snippets)
+ CONTENT='snippets'
+ CONTENT_LABEL='Snippets'
+ ;;
+ *)
+ msg_error "Invalid storage class '$CLASS'"
+ return 1
+ ;;
+ esac
+
+ declare -A STORAGE_MAP
+ local -a MENU=()
+ local COL_WIDTH=0
+
+ while read -r TAG TYPE _ TOTAL USED FREE _; do
+ [[ -n "$TAG" && -n "$TYPE" ]] || continue
+ local DISPLAY="${TAG} (${TYPE})"
+ local USED_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$USED")
+ local FREE_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$FREE")
+ local INFO="Free: ${FREE_FMT}B Used: ${USED_FMT}B"
+ STORAGE_MAP["$DISPLAY"]="$TAG"
+ MENU+=("$DISPLAY" "$INFO" "OFF")
+ ((${#DISPLAY} > COL_WIDTH)) && COL_WIDTH=${#DISPLAY}
+ done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
+
+ if [[ ${#MENU[@]} -eq 0 ]]; then
+ msg_error "No storage found for content type '$CONTENT'."
+ return 2
+ fi
+
+ if [[ $((${#MENU[@]} / 3)) -eq 1 ]]; then
+ STORAGE_RESULT="${STORAGE_MAP[${MENU[0]}]}"
+ STORAGE_INFO="${MENU[1]}"
+ return 0
+ fi
+
+ local WIDTH=$((COL_WIDTH + 42))
+ while true; do
+ local DISPLAY_SELECTED
+ DISPLAY_SELECTED=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" \
+ --title "Storage Pools" \
+ --radiolist "Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
+ 16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3) || { exit_script; }
+
+ DISPLAY_SELECTED=$(sed 's/[[:space:]]*$//' <<<"$DISPLAY_SELECTED")
+ if [[ -z "$DISPLAY_SELECTED" || -z "${STORAGE_MAP[$DISPLAY_SELECTED]+_}" ]]; then
+ whiptail --msgbox "No valid storage selected. Please try again." 8 58
+ continue
+ fi
+ STORAGE_RESULT="${STORAGE_MAP[$DISPLAY_SELECTED]}"
+ for ((i = 0; i < ${#MENU[@]}; i += 3)); do
+ if [[ "${MENU[$i]}" == "$DISPLAY_SELECTED" ]]; then
+ STORAGE_INFO="${MENU[$i + 1]}"
+ break
+ fi
+ done
+ return 0
+ done
+}
+
+create_lxc_container() {
+ # ------------------------------------------------------------------------------
+ # Optional verbose mode (debug tracing)
+ # ------------------------------------------------------------------------------
+ if [[ "${CREATE_LXC_VERBOSE:-no}" == "yes" ]]; then set -x; fi
+
+ # ------------------------------------------------------------------------------
+ # Helpers (dynamic versioning / template parsing)
+ # ------------------------------------------------------------------------------
+ pkg_ver() { dpkg-query -W -f='${Version}\n' "$1" 2>/dev/null || echo ""; }
+ pkg_cand() { apt-cache policy "$1" 2>/dev/null | awk '/Candidate:/ {print $2}'; }
+
+ ver_ge() { dpkg --compare-versions "$1" ge "$2"; }
+ ver_gt() { dpkg --compare-versions "$1" gt "$2"; }
+ ver_lt() { dpkg --compare-versions "$1" lt "$2"; }
+
+ # Extract Debian OS minor from template name: debian-13-standard_13.1-1_amd64.tar.zst => "13.1"
+ parse_template_osver() { sed -n 's/.*_\([0-9][0-9]*\(\.[0-9]\+\)\?\)-.*/\1/p' <<<"$1"; }
+
+ # Offer upgrade for pve-container/lxc-pve if candidate > installed; optional auto-retry pct create
+ # Returns:
+ # 0 = no upgrade needed
+ # 1 = upgraded (and if do_retry=yes and retry succeeded, creation done)
+ # 2 = user declined
+ # 3 = upgrade attempted but failed OR retry failed
+ offer_lxc_stack_upgrade_and_maybe_retry() {
+ local do_retry="${1:-no}" # yes|no
+ local _pvec_i _pvec_c _lxcp_i _lxcp_c need=0
+
+ _pvec_i="$(pkg_ver pve-container)"
+ _lxcp_i="$(pkg_ver lxc-pve)"
+ _pvec_c="$(pkg_cand pve-container)"
+ _lxcp_c="$(pkg_cand lxc-pve)"
+
+ if [[ -n "$_pvec_c" && "$_pvec_c" != "none" ]]; then
+ ver_gt "$_pvec_c" "${_pvec_i:-0}" && need=1
+ fi
+ if [[ -n "$_lxcp_c" && "$_lxcp_c" != "none" ]]; then
+ ver_gt "$_lxcp_c" "${_lxcp_i:-0}" && need=1
+ fi
+ if [[ $need -eq 0 ]]; then
+ msg_debug "No newer candidate for pve-container/lxc-pve (installed=$_pvec_i/$_lxcp_i, cand=$_pvec_c/$_lxcp_c)"
+ return 0
+ fi
+
+ echo
+ echo "An update for the Proxmox LXC stack is available:"
+ echo " pve-container: installed=${_pvec_i:-n/a} candidate=${_pvec_c:-n/a}"
+ echo " lxc-pve : installed=${_lxcp_i:-n/a} candidate=${_lxcp_c:-n/a}"
+ echo
+ read -rp "Do you want to upgrade now? [y/N] " _ans
+ case "${_ans,,}" in
+ y | yes)
+ msg_info "Upgrading Proxmox LXC stack (pve-container, lxc-pve)"
+ if apt-get update -qq >/dev/null && apt-get install -y --only-upgrade pve-container lxc-pve >/dev/null; then
+ msg_ok "LXC stack upgraded."
+ if [[ "$do_retry" == "yes" ]]; then
+ msg_info "Retrying container creation after upgrade"
+ if pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ msg_ok "Container created successfully after upgrade."
+ return 0
+ else
+ msg_error "pct create still failed after upgrade. See $LOGFILE"
+ return 3
+ fi
+ fi
+ return 1
+ else
+ msg_error "Upgrade failed. Please check APT output."
+ return 3
+ fi
+ ;;
+ *) return 2 ;;
+ esac
+ }
+
+ # ------------------------------------------------------------------------------
+ # Required input variables
+ # ------------------------------------------------------------------------------
+ [[ "${CTID:-}" ]] || {
+ msg_error "You need to set 'CTID' variable."
+ exit 203
+ }
+ [[ "${PCT_OSTYPE:-}" ]] || {
+ msg_error "You need to set 'PCT_OSTYPE' variable."
+ exit 204
+ }
+
+ msg_debug "CTID=$CTID"
+ msg_debug "PCT_OSTYPE=$PCT_OSTYPE"
+ msg_debug "PCT_OSVERSION=${PCT_OSVERSION:-default}"
+
+ # ID checks
+ [[ "$CTID" -ge 100 ]] || {
+ msg_error "ID cannot be less than 100."
+ exit 205
+ }
+ if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
+ echo -e "ID '$CTID' is already in use."
+ unset CTID
+ msg_error "Cannot use ID that is already in use."
+ exit 206
+ fi
+
+ # Storage capability check
+ check_storage_support "rootdir" || {
+ msg_error "No valid storage found for 'rootdir' [Container]"
+ exit 1
+ }
+ check_storage_support "vztmpl" || {
+ msg_error "No valid storage found for 'vztmpl' [Template]"
+ exit 1
+ }
+
+ # Template storage selection
+ if resolve_storage_preselect template "${TEMPLATE_STORAGE:-}"; then
+ TEMPLATE_STORAGE="$STORAGE_RESULT"
+ TEMPLATE_STORAGE_INFO="$STORAGE_INFO"
+ msg_ok "Storage ${BL}${TEMPLATE_STORAGE}${CL} (${TEMPLATE_STORAGE_INFO}) [Template]"
+ else
+ while true; do
+ if [[ -z "${var_template_storage:-}" ]]; then
+ if select_storage template; then
+ TEMPLATE_STORAGE="$STORAGE_RESULT"
+ TEMPLATE_STORAGE_INFO="$STORAGE_INFO"
+ msg_ok "Storage ${BL}${TEMPLATE_STORAGE}${CL} (${TEMPLATE_STORAGE_INFO}) [Template]"
+ break
+ fi
+ fi
+ done
+ fi
+
+ # Container storage selection
+ if resolve_storage_preselect container "${CONTAINER_STORAGE:-}"; then
+ CONTAINER_STORAGE="$STORAGE_RESULT"
+ CONTAINER_STORAGE_INFO="$STORAGE_INFO"
+ msg_ok "Storage ${BL}${CONTAINER_STORAGE}${CL} (${CONTAINER_STORAGE_INFO}) [Container]"
+ else
+ if [[ -z "${var_container_storage:-}" ]]; then
+ if select_storage container; then
+ CONTAINER_STORAGE="$STORAGE_RESULT"
+ CONTAINER_STORAGE_INFO="$STORAGE_INFO"
+ msg_ok "Storage ${BL}${CONTAINER_STORAGE}${CL} (${CONTAINER_STORAGE_INFO}) [Container]"
+ fi
+ fi
+ fi
+
+ # Validate content types
+ msg_info "Validating content types of storage '$CONTAINER_STORAGE'"
+ STORAGE_CONTENT=$(grep -A4 -E "^(zfspool|dir|lvmthin|lvm): $CONTAINER_STORAGE" /etc/pve/storage.cfg | grep content | awk '{$1=""; print $0}' | xargs)
+ msg_debug "Storage '$CONTAINER_STORAGE' has content types: $STORAGE_CONTENT"
+ grep -qw "rootdir" <<<"$STORAGE_CONTENT" || {
+ msg_error "Storage '$CONTAINER_STORAGE' does not support 'rootdir'. Cannot create LXC."
+ exit 217
+ }
+ $STD msg_ok "Storage '$CONTAINER_STORAGE' supports 'rootdir'"
+
+ msg_info "Validating content types of template storage '$TEMPLATE_STORAGE'"
+ TEMPLATE_CONTENT=$(grep -A4 -E "^[^:]+: $TEMPLATE_STORAGE" /etc/pve/storage.cfg | grep content | awk '{$1=""; print $0}' | xargs)
+ msg_debug "Template storage '$TEMPLATE_STORAGE' has content types: $TEMPLATE_CONTENT"
+ if ! grep -qw "vztmpl" <<<"$TEMPLATE_CONTENT"; then
+ msg_warn "Template storage '$TEMPLATE_STORAGE' does not declare 'vztmpl'. This may cause pct create to fail."
+ else
+ $STD msg_ok "Template storage '$TEMPLATE_STORAGE' supports 'vztmpl'"
+ fi
+
+ # Free space check
+ STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
+ REQUIRED_KB=$((${PCT_DISK_SIZE:-8} * 1024 * 1024))
+ [[ "$STORAGE_FREE" -ge "$REQUIRED_KB" ]] || {
+ msg_error "Not enough space on '$CONTAINER_STORAGE'. Needed: ${PCT_DISK_SIZE:-8}G."
+ exit 214
+ }
+
+ # Cluster quorum (if cluster)
+ if [[ -f /etc/pve/corosync.conf ]]; then
+ msg_info "Checking cluster quorum"
+ if ! pvecm status | awk -F':' '/^Quorate/ { exit ($2 ~ /Yes/) ? 0 : 1 }'; then
+ msg_error "Cluster is not quorate. Start all nodes or configure quorum device (QDevice)."
+ exit 210
+ fi
+ msg_ok "Cluster is quorate"
+ fi
+
+ # ------------------------------------------------------------------------------
+ # Template discovery & validation
+ # ------------------------------------------------------------------------------
+ TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
+ case "$PCT_OSTYPE" in
+ debian | ubuntu) TEMPLATE_PATTERN="-standard_" ;;
+ alpine | fedora | rocky | centos) TEMPLATE_PATTERN="-default_" ;;
+ *) TEMPLATE_PATTERN="" ;;
+ esac
+
+ msg_info "Searching for template '$TEMPLATE_SEARCH'"
+
+ # Build regex patterns outside awk/grep for clarity
+ SEARCH_PATTERN="^${TEMPLATE_SEARCH}"
+
+ #echo "[DEBUG] TEMPLATE_SEARCH='$TEMPLATE_SEARCH'"
+ #echo "[DEBUG] SEARCH_PATTERN='$SEARCH_PATTERN'"
+ #echo "[DEBUG] TEMPLATE_PATTERN='$TEMPLATE_PATTERN'"
+
+ mapfile -t LOCAL_TEMPLATES < <(
+ pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
+ awk -v search="${SEARCH_PATTERN}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
+ sed 's|.*/||' | sort -t - -k 2 -V
+ )
+
+ pveam update >/dev/null 2>&1 || msg_warn "Could not update template catalog (pveam update failed)."
+
+ msg_ok "Template search completed"
+
+ #echo "[DEBUG] pveam available output (first 5 lines with .tar files):"
+ #pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | head -5 | sed 's/^/ /'
+
+ set +u
+ mapfile -t ONLINE_TEMPLATES < <(pveam available -section system 2>/dev/null | grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' | awk '{print $2}' | grep -E "${SEARCH_PATTERN}.*${TEMPLATE_PATTERN}" | sort -t - -k 2 -V 2>/dev/null || true)
+ #echo "[DEBUG] After filtering: ${#ONLINE_TEMPLATES[@]} online templates found"
+ set -u
+
+ ONLINE_TEMPLATE=""
+ [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
+
+ #msg_debug "SEARCH_PATTERN='${SEARCH_PATTERN}' TEMPLATE_PATTERN='${TEMPLATE_PATTERN}'"
+ #msg_debug "Found ${#LOCAL_TEMPLATES[@]} local templates, ${#ONLINE_TEMPLATES[@]} online templates"
+ if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
+ #msg_debug "First 3 online templates:"
+ count=0
+ for idx in "${!ONLINE_TEMPLATES[@]}"; do
+ #msg_debug " [$idx]: ${ONLINE_TEMPLATES[$idx]}"
+ ((count++))
+ [[ $count -ge 3 ]] && break
+ done
+ fi
+ #msg_debug "ONLINE_TEMPLATE='$ONLINE_TEMPLATE'"
+
+ if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
+ TEMPLATE="${LOCAL_TEMPLATES[-1]}"
+ TEMPLATE_SOURCE="local"
+ else
+ TEMPLATE="$ONLINE_TEMPLATE"
+ TEMPLATE_SOURCE="online"
+ fi
+
+ # If still no template, try to find alternatives
+ if [[ -z "$TEMPLATE" ]]; then
+ echo ""
+ echo "[DEBUG] No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
+
+ # Get all available versions for this OS type
+ mapfile -t AVAILABLE_VERSIONS < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk -F'\t' '{print $1}' |
+ grep "^${PCT_OSTYPE}-" |
+ sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
+ sort -u -V 2>/dev/null
+ )
+
+ if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
+ echo ""
+ echo "${BL}Available ${PCT_OSTYPE} versions:${CL}"
+ for i in "${!AVAILABLE_VERSIONS[@]}"; do
+ echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
+ done
+ echo ""
+ read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or press Enter to cancel: " choice
+
+ if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
+ PCT_OSVERSION="${AVAILABLE_VERSIONS[$((choice - 1))]}"
+ TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION}"
+ SEARCH_PATTERN="^${TEMPLATE_SEARCH}-"
+
+ #echo "[DEBUG] Retrying with version: $PCT_OSVERSION"
+
+ mapfile -t ONLINE_TEMPLATES < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk -F'\t' '{print $1}' |
+ grep -E "${SEARCH_PATTERN}.*${TEMPLATE_PATTERN}" |
+ sort -t - -k 2 -V 2>/dev/null || true
+ )
+
+ if [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]]; then
+ TEMPLATE="${ONLINE_TEMPLATES[-1]}"
+ TEMPLATE_SOURCE="online"
+ #echo "[DEBUG] Found alternative: $TEMPLATE"
+ else
+ msg_error "No templates available for ${PCT_OSTYPE} ${PCT_OSVERSION}"
+ exit 225
+ fi
+ else
+ msg_custom "🚫" "${YW}" "Installation cancelled"
+ exit 0
+ fi
+ else
+ msg_error "No ${PCT_OSTYPE} templates available at all"
+ exit 225
+ fi
+ fi
+
+ #echo "[DEBUG] Selected TEMPLATE='$TEMPLATE' SOURCE='$TEMPLATE_SOURCE'"
+ #msg_debug "Selected TEMPLATE='$TEMPLATE' SOURCE='$TEMPLATE_SOURCE'"
+
+ TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
+ if [[ -z "$TEMPLATE_PATH" ]]; then
+ TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
+ [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
+ fi
+
+ # If we still don't have a path but have a valid template name, construct it
+ if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
+ TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
+ fi
+
+ [[ -n "$TEMPLATE_PATH" ]] || {
+ if [[ -z "$TEMPLATE" ]]; then
+ msg_error "Template ${PCT_OSTYPE} ${PCT_OSVERSION} not available"
+
+ # Get available versions
+ mapfile -t AVAILABLE_VERSIONS < <(
+ pveam available -section system 2>/dev/null |
+ grep "^${PCT_OSTYPE}-" |
+ sed -E 's/.*'"${PCT_OSTYPE}"'-([0-9]+\.[0-9]+).*/\1/' |
+ grep -E '^[0-9]+\.[0-9]+$' |
+ sort -u -V 2>/dev/null || sort -u
+ )
+
+ if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
+ echo -e "\n${BL}Available versions:${CL}"
+ for i in "${!AVAILABLE_VERSIONS[@]}"; do
+ echo " [$((i + 1))] ${AVAILABLE_VERSIONS[$i]}"
+ done
+
+ echo ""
+ read -p "Select version [1-${#AVAILABLE_VERSIONS[@]}] or Enter to exit: " choice
+
+ if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le ${#AVAILABLE_VERSIONS[@]} ]]; then
+ export var_version="${AVAILABLE_VERSIONS[$((choice - 1))]}"
+ export PCT_OSVERSION="$var_version"
+ msg_ok "Switched to ${PCT_OSTYPE} ${var_version}"
+
+ # Retry template search with new version
+ TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
+ SEARCH_PATTERN="^${TEMPLATE_SEARCH}-"
+
+ mapfile -t LOCAL_TEMPLATES < <(
+ pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
+ awk -v search="${SEARCH_PATTERN}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
+ sed 's|.*/||' | sort -t - -k 2 -V
+ )
+ mapfile -t ONLINE_TEMPLATES < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk -F'\t' '{print $1}' |
+ grep -E "${SEARCH_PATTERN}.*${TEMPLATE_PATTERN}" |
+ sort -t - -k 2 -V 2>/dev/null || true
+ )
+ ONLINE_TEMPLATE=""
+ [[ ${#ONLINE_TEMPLATES[@]} -gt 0 ]] && ONLINE_TEMPLATE="${ONLINE_TEMPLATES[-1]}"
+
+ if [[ ${#LOCAL_TEMPLATES[@]} -gt 0 ]]; then
+ TEMPLATE="${LOCAL_TEMPLATES[-1]}"
+ TEMPLATE_SOURCE="local"
+ else
+ TEMPLATE="$ONLINE_TEMPLATE"
+ TEMPLATE_SOURCE="online"
+ fi
+
+ TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null || true)"
+ if [[ -z "$TEMPLATE_PATH" ]]; then
+ TEMPLATE_BASE=$(awk -v s="$TEMPLATE_STORAGE" '$1==s {f=1} f && /path/ {print $2; exit}' /etc/pve/storage.cfg)
+ [[ -n "$TEMPLATE_BASE" ]] && TEMPLATE_PATH="$TEMPLATE_BASE/template/cache/$TEMPLATE"
+ fi
+
+ # If we still don't have a path but have a valid template name, construct it
+ if [[ -z "$TEMPLATE_PATH" && -n "$TEMPLATE" ]]; then
+ TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
+ fi
+
+ [[ -n "$TEMPLATE_PATH" ]] || {
+ msg_error "Template still not found after version change"
+ exit 220
+ }
+ else
+ msg_custom "🚫" "${YW}" "Installation cancelled"
+ exit 1
+ fi
+ else
+ msg_error "No ${PCT_OSTYPE} templates available"
+ exit 220
+ fi
+ fi
+ }
+
+ # Validate that we found a template
+ if [[ -z "$TEMPLATE" ]]; then
+ msg_error "No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}"
+ msg_custom "ℹ️" "${YW}" "Please check:"
+ msg_custom " •" "${YW}" "Is pveam catalog available? (run: pveam available -section system)"
+ msg_custom " •" "${YW}" "Does the template exist for your OS version?"
+ exit 225
+ fi
+
+ msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
+ msg_debug "Resolved TEMPLATE_PATH=$TEMPLATE_PATH"
+
+ NEED_DOWNLOAD=0
+ if [[ ! -f "$TEMPLATE_PATH" ]]; then
+ msg_info "Template not present locally – will download."
+ NEED_DOWNLOAD=1
+ elif [[ ! -r "$TEMPLATE_PATH" ]]; then
+ msg_error "Template file exists but is not readable – check permissions."
+ exit 221
+ elif [[ "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
+ if [[ -n "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Template file too small (<1MB) – re-downloading."
+ NEED_DOWNLOAD=1
+ else
+ msg_warn "Template looks too small, but no online version exists. Keeping local file."
+ fi
+ elif ! tar -tf "$TEMPLATE_PATH" &>/dev/null; then
+ if [[ -n "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Template appears corrupted – re-downloading."
+ NEED_DOWNLOAD=1
+ else
+ msg_warn "Template appears corrupted, but no online version exists. Keeping local file."
+ fi
+ else
+ $STD msg_ok "Template $TEMPLATE is present and valid."
+ fi
+
+ if [[ "$TEMPLATE_SOURCE" == "local" && -n "$ONLINE_TEMPLATE" && "$TEMPLATE" != "$ONLINE_TEMPLATE" ]]; then
+ msg_warn "Local template is outdated: $TEMPLATE (latest available: $ONLINE_TEMPLATE)"
+ if whiptail --yesno "A newer template is available:\n$ONLINE_TEMPLATE\n\nDo you want to download and use it instead?" 12 70; then
+ TEMPLATE="$ONLINE_TEMPLATE"
+ NEED_DOWNLOAD=1
+ else
+ msg_custom "ℹ️" "${BL}" "Continuing with local template $TEMPLATE"
+ fi
+ fi
+
+ if [[ "$NEED_DOWNLOAD" -eq 1 ]]; then
+ [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
+ for attempt in {1..3}; do
+ msg_info "Attempt $attempt: Downloading template $TEMPLATE to $TEMPLATE_STORAGE"
+ if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1; then
+ msg_ok "Template download successful."
+ break
+ fi
+ if [[ $attempt -eq 3 ]]; then
+ msg_error "Failed after 3 attempts. Please check network access, permissions, or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
+ exit 222
+ fi
+ sleep $((attempt * 5))
+ done
+ fi
+
+ if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then
+ msg_error "Template $TEMPLATE not available in storage $TEMPLATE_STORAGE after download."
+ exit 223
+ fi
+
+ # ------------------------------------------------------------------------------
+ # Dynamic preflight for Debian 13.x: offer upgrade if available (no hard mins)
+ # ------------------------------------------------------------------------------
+ if [[ "$PCT_OSTYPE" == "debian" ]]; then
+ OSVER="$(parse_template_osver "$TEMPLATE")"
+ if [[ -n "$OSVER" ]]; then
+ # Proactive, aber ohne Abbruch – nur Angebot
+ offer_lxc_stack_upgrade_and_maybe_retry "no" || true
+ fi
+ fi
+
+ # ------------------------------------------------------------------------------
+ # Create LXC Container
+ # ------------------------------------------------------------------------------
+ msg_info "Creating LXC container"
+
+ # Ensure subuid/subgid entries exist
+ grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
+ grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
+
+ # Assemble pct options
+ PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
+ [[ " ${PCT_OPTIONS[*]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
+
+ # Lock by template file (avoid concurrent downloads/creates)
+ lockfile="/tmp/template.${TEMPLATE}.lock"
+ 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
+ }
+
+ LOGFILE="/tmp/pct_create_${CTID}.log"
+ msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
+ msg_debug "Logfile: $LOGFILE"
+
+ # First attempt
+ if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
+ msg_error "Container creation failed on ${TEMPLATE_STORAGE}. Checking template..."
+
+ # 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."
+ 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
+ fi
+
+ # Retry after repair
+ if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ # Fallback to local storage
+ if [[ "$TEMPLATE_STORAGE" != "local" ]]; then
+ msg_warn "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..."
+ pveam download local "$TEMPLATE" >/dev/null 2>&1
+ fi
+ if pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ msg_ok "Container successfully created using local fallback."
+ else
+ # --- Dynamic stack upgrade + auto-retry on the well-known error pattern ---
+ if grep -qiE 'unsupported .* version' "$LOGFILE"; then
+ echo
+ echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
+ echo "We can try to upgrade 'pve-container' and 'lxc-pve' now and retry automatically."
+ offer_lxc_stack_upgrade_and_maybe_retry "yes"
+ rc=$?
+ case $rc in
+ 0) : ;; # success - container created, continue
+ 2)
+ echo "Upgrade was declined. Please update and re-run:
+ apt update && apt install --only-upgrade pve-container lxc-pve"
+ exit 231
+ ;;
+ 3)
+ echo "Upgrade and/or retry failed. Please inspect: $LOGFILE"
+ exit 231
+ ;;
+ esac
+ else
+ msg_error "Container creation failed even with local fallback. See $LOGFILE"
+ if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
+ set -x
+ bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
+ set +x
+ fi
+ exit 209
+ fi
+ fi
+ else
+ msg_error "Container creation failed on local storage. See $LOGFILE"
+ # --- Dynamic stack upgrade + auto-retry on the well-known error pattern ---
+ if grep -qiE 'unsupported .* version' "$LOGFILE"; then
+ echo
+ echo "pct reported 'unsupported ... version' – your LXC stack might be too old for this template."
+ echo "We can try to upgrade 'pve-container' and 'lxc-pve' now and retry automatically."
+ offer_lxc_stack_upgrade_and_maybe_retry "yes"
+ rc=$?
+ case $rc in
+ 0) : ;; # success - container created, continue
+ 2)
+ echo "Upgrade was declined. Please update and re-run:
+ apt update && apt install --only-upgrade pve-container lxc-pve"
+ exit 231
+ ;;
+ 3)
+ echo "Upgrade and/or retry failed. Please inspect: $LOGFILE"
+ exit 231
+ ;;
+ esac
+ else
+ msg_error "Container creation failed. See $LOGFILE"
+ if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
+ set -x
+ bash -x -c "pct create $CTID local:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}" 2>&1 | tee -a "$LOGFILE"
+ set +x
+ fi
+ exit 209
+ fi
+ fi
+ fi
+ fi
+
+ # Verify container exists
+ pct list | awk '{print $1}' | grep -qx "$CTID" || {
+ msg_error "Container ID $CTID not listed in 'pct list'. See $LOGFILE"
+ exit 215
+ }
+
+ # Verify config rootfs
+ grep -q '^rootfs:' "/etc/pve/lxc/$CTID.conf" || {
+ msg_error "RootFS entry missing in container config. See $LOGFILE"
+ exit 216
+ }
+
+ msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
+}
+
+# ==============================================================================
+# SECTION 9: POST-INSTALLATION & FINALIZATION
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# description()
+#
+# - Sets container description with formatted HTML content
+# - Includes:
+# * Community-Scripts logo
+# * Application name
+# * Links to GitHub, Discussions, Issues
+# * Ko-fi donation badge
+# - Restarts ping-instances.service if present (monitoring)
+# - Posts final "done" status to API telemetry
+# ------------------------------------------------------------------------------
+description() {
+ IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
+
+ # Generate LXC Description
+ DESCRIPTION=$(
+ cat <
+
+
+
+
+ ${APP} LXC
+
+
+
+
+
+
+
+
+
+ GitHub
+
+
+
+ Discussions
+
+
+
+ Issues
+
+
+EOF
+ )
+ pct set "$CTID" -description "$DESCRIPTION"
+
+ if [[ -f /etc/systemd/system/ping-instances.service ]]; then
+ systemctl start ping-instances.service
+ fi
+
+ post_update_to_api "done" "none"
+}
+
+# ==============================================================================
+# SECTION 10: ERROR HANDLING & EXIT TRAPS
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# api_exit_script()
+#
+# - Exit trap handler for reporting to API telemetry
+# - Captures exit code and reports to API using centralized error descriptions
+# - Uses explain_exit_code() from error_handler.func for consistent error messages
+# - Posts failure status with exit code to API (error description added automatically)
+# - Only executes on non-zero exit codes
+# ------------------------------------------------------------------------------
+api_exit_script() {
+ exit_code=$?
+ if [ $exit_code -ne 0 ]; then
+ post_update_to_api "failed" "$exit_code"
+ fi
+}
+
+if command -v pveversion >/dev/null 2>&1; then
+ trap 'api_exit_script' EXIT
+fi
+trap 'post_update_to_api "failed" "$BASH_COMMAND"' ERR
+trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
+trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
diff --git a/misc/build.func b/misc/build.func
index e8f1ed6c7..00b7fa549 100644
--- a/misc/build.func
+++ b/misc/build.func
@@ -535,35 +535,6 @@ base_settings() {
TAGS="community-script,${var_tags:-}"
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
ENABLE_TUN=${var_tun:-"${1:-no}"}
- ENABLE_NESTING=${var_nesting:-"${1:-1}"}
- ENABLE_KEYCTL=${var_keyctl:-"${1:-0}"}
- ALLOW_MOUNT_FS=${var_mount_fs:-""}
- ENABLE_MKNOD=${var_mknod:-"${1:-0}"}
- PROTECT_CT=${var_protection:-"${1:-no}"}
- CT_TIMEZONE=${var_timezone:-""}
-
- # Normalize feature flags to 0/1 immediately (pct requires numeric values, not yes/no)
- # This must happen here before any usage of these variables
- case "${ENABLE_NESTING,,}" in
- yes | true) ENABLE_NESTING="1" ;;
- no | false) ENABLE_NESTING="0" ;;
- esac
- case "${ENABLE_KEYCTL,,}" in
- yes | true) ENABLE_KEYCTL="1" ;;
- no | false) ENABLE_KEYCTL="0" ;;
- esac
- case "${ENABLE_MKNOD,,}" in
- yes | true) ENABLE_MKNOD="1" ;;
- no | false) ENABLE_MKNOD="0" ;;
- esac
- case "${ENABLE_FUSE,,}" in
- yes | true) ENABLE_FUSE="1" ;;
- no | false) ENABLE_FUSE="0" ;;
- esac
- case "${PROTECT_CT,,}" in
- yes | true) PROTECT_CT="1" ;;
- no | false) PROTECT_CT="0" ;;
- esac
# Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
if [ -z "$var_os" ]; then
@@ -1795,7 +1766,16 @@ install_script() {
fi
NEXTID=$(pvesh get /cluster/nextid)
- timezone=$(cat /etc/timezone)
+
+ # Get timezone using timedatectl (Debian 13+ compatible)
+ # Fallback to /etc/timezone for older systems
+ if command -v timedatectl >/dev/null 2>&1; then
+ timezone=$(timedatectl show --value --property=Timezone 2>/dev/null || echo "UTC")
+ elif [ -f /etc/timezone ]; then
+ timezone=$(cat /etc/timezone)
+ else
+ timezone="UTC"
+ fi
# Show APP Header
header_info
@@ -2289,35 +2269,19 @@ build_container() {
none) ;;
esac
- # Build FEATURES array with advanced settings
- # Note: All feature flags are already normalized to 0/1 in default_settings()
- # Proxmox requires each feature as a separate parameter, not comma-separated string
- FEATURES_ARRAY=()
- FEATURES_ARRAY+=("nesting=${ENABLE_NESTING}")
-
- # keyctl: needed for Docker inside containers (systemd-networkd workaround)
- # Typically needed for unprivileged containers with Docker
- if [ "$CT_TYPE" == "1" ] || [ "$ENABLE_KEYCTL" == "1" ]; then
- FEATURES_ARRAY+=("keyctl=1")
+ # Build FEATURES string (simple working version)
+ if [ "$CT_TYPE" == "1" ]; then
+ FEATURES="keyctl=1,nesting=1"
+ else
+ FEATURES="nesting=1"
fi
- # mknod: allow device node creation (requires kernel 5.3+, experimental)
- if [ "$ENABLE_MKNOD" == "1" ]; then
- FEATURES_ARRAY+=("mknod=1")
+ if [ "$ENABLE_FUSE" == "yes" ]; then
+ FEATURES="$FEATURES,fuse=1"
fi
- # FUSE: required for rclone, mergerfs, AppImage, etc.
- if [ "$ENABLE_FUSE" == "1" ]; then
- FEATURES_ARRAY+=("fuse=1")
- fi
-
- # mount: allow specific filesystems (e.g., nfs, ext4, etc.)
- # Format: mount=fstype1;fstype2;fstype3 (semicolon-separated, not comma!)
- if [ -n "$ALLOW_MOUNT_FS" ]; then
- # Replace commas with semicolons for proper pct syntax
- ALLOW_MOUNT_FS_FORMATTED="${ALLOW_MOUNT_FS//,/;}"
- FEATURES_ARRAY+=("mount=$ALLOW_MOUNT_FS_FORMATTED")
- fi
+ # NEW IMPLEMENTATION (Fixed): Build PCT_OPTIONS properly
+ # Key insight: Bash cannot export arrays, so we build the options as a string
TEMP_DIR=$(mktemp -d)
pushd "$TEMP_DIR" >/dev/null
@@ -2326,19 +2290,11 @@ build_container() {
else
export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/luismco/ProxmoxVED/refs/heads/byparr/misc/install.func)"
fi
+
+ # Core exports for install.func
export DIAGNOSTICS="$DIAGNOSTICS"
export RANDOM_UUID="$RANDOM_UUID"
export SESSION_ID="$SESSION_ID"
- export BUILD_LOG="$BUILD_LOG"
- export INSTALL_LOG="/root/.install-${SESSION_ID}.log"
- export dev_mode="${dev_mode:-}"
- export DEV_MODE_MOTD="${DEV_MODE_MOTD:-false}"
- export DEV_MODE_KEEP="${DEV_MODE_KEEP:-false}"
- export DEV_MODE_TRACE="${DEV_MODE_TRACE:-false}"
- export DEV_MODE_PAUSE="${DEV_MODE_PAUSE:-false}"
- export DEV_MODE_BREAKPOINT="${DEV_MODE_BREAKPOINT:-false}"
- export DEV_MODE_LOGS="${DEV_MODE_LOGS:-false}"
- export DEV_MODE_DRYRUN="${DEV_MODE_DRYRUN:-false}"
export CACHER="$APT_CACHER"
export CACHER_IP="$APT_CACHER_IP"
export tz="$timezone"
@@ -2352,61 +2308,75 @@ build_container() {
export CTTYPE="$CT_TYPE"
export ENABLE_FUSE="$ENABLE_FUSE"
export ENABLE_TUN="$ENABLE_TUN"
- export ENABLE_NESTING="$ENABLE_NESTING"
- export ENABLE_KEYCTL="$ENABLE_KEYCTL"
- export ENABLE_MKNOD="$ENABLE_MKNOD"
- export ALLOW_MOUNT_FS="$ALLOW_MOUNT_FS"
- export PROTECT_CT="$PROTECT_CT"
- export CT_TIMEZONE="$CT_TIMEZONE"
export PCT_OSTYPE="$var_os"
export PCT_OSVERSION="$var_version"
export PCT_DISK_SIZE="$DISK_SIZE"
- # Build PCT_OPTIONS array (not string) for proper parameter handling
- PCT_OPTIONS=()
+ # DEV_MODE exports (optional, for debugging)
+ export BUILD_LOG="$BUILD_LOG"
+ export INSTALL_LOG="/root/.install-${SESSION_ID}.log"
+ export dev_mode="${dev_mode:-}"
+ export DEV_MODE_MOTD="${DEV_MODE_MOTD:-false}"
+ export DEV_MODE_KEEP="${DEV_MODE_KEEP:-false}"
+ export DEV_MODE_TRACE="${DEV_MODE_TRACE:-false}"
+ export DEV_MODE_PAUSE="${DEV_MODE_PAUSE:-false}"
+ export DEV_MODE_BREAKPOINT="${DEV_MODE_BREAKPOINT:-false}"
+ export DEV_MODE_LOGS="${DEV_MODE_LOGS:-false}"
+ export DEV_MODE_DRYRUN="${DEV_MODE_DRYRUN:-false}"
- # Add features - each as separate -features parameter
- for feature in "${FEATURES_ARRAY[@]}"; do
- PCT_OPTIONS+=("-features" "$feature")
- done
-
- PCT_OPTIONS+=("-hostname" "$HN")
- PCT_OPTIONS+=("-tags" "$TAGS")
+ # Build PCT_OPTIONS as multi-line string
+ PCT_OPTIONS_STRING=" -features $FEATURES
+ -hostname $HN
+ -tags $TAGS"
+ # Add storage if specified
if [ -n "$SD" ]; then
- PCT_OPTIONS+=($SD) # Storage device flags (already formatted)
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ $SD"
fi
+ # Add nameserver if specified
if [ -n "$NS" ]; then
- PCT_OPTIONS+=($NS) # Nameserver flags (already formatted)
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ $NS"
fi
- # Network configuration (single string with all network parameters)
- PCT_OPTIONS+=($NET_STRING)
+ # Network configuration
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ $NET_STRING
+ -onboot 1
+ -cores $CORE_COUNT
+ -memory $RAM_SIZE
+ -unprivileged $CT_TYPE"
- PCT_OPTIONS+=("-onboot" "1")
- PCT_OPTIONS+=("-cores" "$CORE_COUNT")
- PCT_OPTIONS+=("-memory" "$RAM_SIZE")
- PCT_OPTIONS+=("-unprivileged" "$CT_TYPE")
-
- # Protection flag
- if [ "$PROTECT_CT" == "1" ]; then
- PCT_OPTIONS+=("-protection" "1")
+ # Protection flag (if var_protection was set)
+ if [ "${PROTECT_CT:-}" == "1" ] || [ "${PROTECT_CT:-}" == "yes" ]; then
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ -protection 1"
fi
- # Timezone flag
- if [ -n "$CT_TIMEZONE" ]; then
- PCT_OPTIONS+=("-timezone" "$CT_TIMEZONE")
+ # Timezone flag (if var_timezone was set)
+ if [ -n "${CT_TIMEZONE:-}" ]; then
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ -timezone $CT_TIMEZONE"
fi
- # Password flag (already formatted as "-password xxx")
+ # Password (already formatted)
if [ -n "$PW" ]; then
- PCT_OPTIONS+=($PW)
+ PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
+ $PW"
fi
- export PCT_OPTIONS
+ # Export as string (this works, unlike arrays!)
+ export PCT_OPTIONS="$PCT_OPTIONS_STRING"
export TEMPLATE_STORAGE="${var_template_storage:-}"
export CONTAINER_STORAGE="${var_container_storage:-}"
+
+ # # DEBUG: Show final PCT_OPTIONS being exported
+ # echo "[DEBUG] PCT_OPTIONS to be exported:"
+ # echo "$PCT_OPTIONS" | sed 's/^/ /'
+ # echo "[DEBUG] Calling create_lxc_container..."
+
create_lxc_container || exit $?
LXC_CONFIG="/etc/pve/lxc/${CTID}.conf"
@@ -2548,7 +2518,7 @@ EOF
if [[ $gpu_count -eq 1 ]]; then
# Automatic selection for single GPU
selected_gpu="${available_gpus[0]}"
- msg_custom "⚙️" "${GN}" "Automatically configuring ${selected_gpu} GPU passthrough"
+ msg_ok "Automatically configuring ${selected_gpu} GPU passthrough"
else
# Multiple GPUs - ask user
echo -e "\n${INFO} Multiple GPU types detected:"
@@ -2714,7 +2684,9 @@ EOF'
fi
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
- pct exec "$CTID" -- bash -c "tz='$tz'; echo \"\$tz\" >/etc/timezone && ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime"
+ # Set timezone using symlink (Debian 13+ compatible)
+ # Create /etc/timezone for backwards compatibility with older scripts
+ pct exec "$CTID" -- bash -c "tz='$tz'; ln -sf \"/usr/share/zoneinfo/\$tz\" /etc/localtime && echo \"\$tz\" >/etc/timezone || true"
else
msg_warn "Skipping timezone setup – zone '$tz' not found in container"
fi
@@ -2747,8 +2719,8 @@ EOF'
# Show available logs
echo ""
- [[ $build_log_copied == true ]] && echo -e "${GN}✔${CL} Container creation log: ${BL}/tmp/create-lxc-${CTID}-${SESSION_ID}.log${CL}"
- [[ $install_log_copied == true ]] && echo -e "${GN}✔${CL} Installation log: ${BL}/tmp/install-lxc-${CTID}-${SESSION_ID}.log${CL}"
+ [[ "$build_log_copied" == true ]] && echo -e "${GN}✔${CL} Container creation log: ${BL}/tmp/create-lxc-${CTID}-${SESSION_ID}.log${CL}"
+ [[ "$install_log_copied" == true ]] && echo -e "${GN}✔${CL} Installation log: ${BL}/tmp/install-lxc-${CTID}-${SESSION_ID}.log${CL}"
fi
# Dev mode: Keep container or open breakpoint shell
@@ -2888,7 +2860,7 @@ fix_gpu_gids() {
return 0
fi
- msg_custom "🔧" "${BL}" "Detecting and setting correct GPU group IDs"
+ msg_info "Detecting and setting correct GPU group IDs"
# Get actual GIDs from container
local video_gid=$(pct exec "$CTID" -- sh -c "getent group video 2>/dev/null | cut -d: -f3")
@@ -3091,7 +3063,7 @@ create_lxc_container() {
msg_ok "LXC stack upgraded."
if [[ "$do_retry" == "yes" ]]; then
msg_info "Retrying container creation after upgrade"
- if pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ if pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" $PCT_OPTIONS >>"$LOGFILE" 2>&1; then
msg_ok "Container created successfully after upgrade."
return 0
else
@@ -3517,9 +3489,12 @@ create_lxc_container() {
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
- # Assemble pct options
- PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
- [[ " ${PCT_OPTIONS[*]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
+ # PCT_OPTIONS is now a string (exported from build_container)
+ # Add rootfs if not already specified
+ if [[ ! "$PCT_OPTIONS" =~ "-rootfs" ]]; then
+ PCT_OPTIONS="$PCT_OPTIONS
+ -rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}"
+ fi
# Lock by template file (avoid concurrent downloads/creates)
lockfile="/tmp/template.${TEMPLATE}.lock"
@@ -3533,11 +3508,22 @@ create_lxc_container() {
}
LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log"
- msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[*]}"
+
+ # # DEBUG: Show the actual command that will be executed
+ # echo "[DEBUG] ===== PCT CREATE COMMAND DETAILS ====="
+ # echo "[DEBUG] CTID: $CTID"
+ # echo "[DEBUG] Template: ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}"
+ # echo "[DEBUG] PCT_OPTIONS (will be word-split):"
+ # echo "$PCT_OPTIONS" | sed 's/^/ /'
+ # echo "[DEBUG] Full command line:"
+ # echo " pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} $PCT_OPTIONS"
+ # echo "[DEBUG] ========================================"
+
+ msg_debug "pct create command: pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} $PCT_OPTIONS"
msg_debug "Logfile: $LOGFILE"
- # First attempt
- if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >"$LOGFILE" 2>&1; then
+ # 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..."
# Validate template file
@@ -3556,7 +3542,7 @@ create_lxc_container() {
fi
# Retry after repair
- if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ 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..."
@@ -3565,7 +3551,7 @@ create_lxc_container() {
msg_info "Downloading template to local..."
pveam download local "$TEMPLATE" >/dev/null 2>&1
fi
- if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" >>"$LOGFILE" 2>&1; then
+ if ! pct create "$CTID" "local:vztmpl/${TEMPLATE}" $PCT_OPTIONS >>"$LOGFILE" 2>&1; then
# Local fallback also failed - check for LXC stack version issue
if grep -qiE 'unsupported .* version' "$LOGFILE"; then
echo
@@ -3589,7 +3575,7 @@ create_lxc_container() {
msg_error "Container creation failed. See $LOGFILE"
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
set -x
- pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE"
+ pct create "$CTID" "local:vztmpl/${TEMPLATE}" $PCT_OPTIONS 2>&1 | tee -a "$LOGFILE"
set +x
fi
exit 209
@@ -3621,7 +3607,7 @@ create_lxc_container() {
msg_error "Container creation failed. See $LOGFILE"
if whiptail --yesno "pct create failed.\nDo you want to enable verbose debug mode and view detailed logs?" 12 70; then
set -x
- pct create "$CTID" "local:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" 2>&1 | tee -a "$LOGFILE"
+ pct create "$CTID" "local:vztmpl/${TEMPLATE}" $PCT_OPTIONS 2>&1 | tee -a "$LOGFILE"
set +x
fi
exit 209
diff --git a/misc/core.func b/misc/core.func
index 0fdd2c58c..6f50773b8 100644
--- a/misc/core.func
+++ b/misc/core.func
@@ -272,7 +272,7 @@ root_check() {
# pve_check()
#
# - Validates Proxmox VE version compatibility
-# - Supported: PVE 8.0-8.9 and PVE 9.0 only
+# - Supported: PVE 8.0-8.9 and PVE 9.0-9.1
# - Exits with error message if unsupported version detected
# ------------------------------------------------------------------------------
pve_check() {
@@ -290,12 +290,12 @@ pve_check() {
return 0
fi
- # Check for Proxmox VE 9.x: allow ONLY 9.0
+ # Check for Proxmox VE 9.x: allow 9.0–9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
+ if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported."
- msg_error "Supported: Proxmox VE version 9.0"
+ msg_error "Supported: Proxmox VE version 9.0 – 9.1"
exit 1
fi
return 0
@@ -303,7 +303,7 @@ pve_check() {
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
+ msg_error "Supported versions: Proxmox VE 8.0 – 8.9 or 9.0 – 9.1"
exit 1
}
@@ -686,7 +686,7 @@ get_header() {
local app_type=${APP_TYPE:-ct} # Default zu 'ct' falls nicht gesetzt
local header_url="https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/${app_type}/headers/${app_name}"
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
-
+
mkdir -p "$(dirname "$local_header_path")"
if [ ! -s "$local_header_path" ]; then
@@ -817,7 +817,7 @@ cleanup_lxc() {
# Python pip
if command -v pip &>/dev/null; then $STD pip cache purge || true; fi
# Python uv
- if command -v uv &>/dev/null; then $STD uv cache clear || true; fi
+ if command -v uv &>/dev/null; then $STD uv cache clean || true; fi
# Node.js npm
if command -v npm &>/dev/null; then $STD npm cache clean --force || true; fi
# Node.js yarn
diff --git a/misc/build.func.backup-20251029-123804 b/misc/deferred/build.func.backup-20251029-123804
similarity index 100%
rename from misc/build.func.backup-20251029-123804
rename to misc/deferred/build.func.backup-20251029-123804
diff --git a/misc/build.func.backup-20251029-124205 b/misc/deferred/build.func.backup-20251029-124205
similarity index 100%
rename from misc/build.func.backup-20251029-124205
rename to misc/deferred/build.func.backup-20251029-124205
diff --git a/misc/build.func.backup-20251029-124307 b/misc/deferred/build.func.backup-20251029-124307
similarity index 100%
rename from misc/build.func.backup-20251029-124307
rename to misc/deferred/build.func.backup-20251029-124307
diff --git a/misc/build.func.backup-20251029-124334 b/misc/deferred/build.func.backup-20251029-124334
similarity index 100%
rename from misc/build.func.backup-20251029-124334
rename to misc/deferred/build.func.backup-20251029-124334
diff --git a/misc/build.func.backup-refactoring-20251029-125644 b/misc/deferred/build.func.backup-refactoring-20251029-125644
similarity index 100%
rename from misc/build.func.backup-refactoring-20251029-125644
rename to misc/deferred/build.func.backup-refactoring-20251029-125644
diff --git a/misc/install copy.func b/misc/install copy.func
new file mode 100644
index 000000000..e9e319576
--- /dev/null
+++ b/misc/install copy.func
@@ -0,0 +1,277 @@
+# Copyright (c) 2021-2025 tteck
+# Author: tteck (tteckster)
+# Co-Author: MickLesk
+# Co-Author: michelroegl-brunner
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+
+# ==============================================================================
+# INSTALL.FUNC - CONTAINER INSTALLATION & SETUP
+# ==============================================================================
+#
+# This file provides installation functions executed inside LXC containers
+# after creation. Handles:
+#
+# - Network connectivity verification (IPv4/IPv6)
+# - OS updates and package installation
+# - DNS resolution checks
+# - MOTD and SSH configuration
+# - Container customization and auto-login
+#
+# Usage:
+# - Sourced by -install.sh scripts
+# - Executes via pct exec inside container
+# - Requires internet connectivity
+#
+# ==============================================================================
+
+# ==============================================================================
+# SECTION 1: INITIALIZATION
+# ==============================================================================
+
+if ! command -v curl >/dev/null 2>&1; then
+ printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
+ apt-get update >/dev/null 2>&1
+ apt-get install -y curl >/dev/null 2>&1
+fi
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/core.func)
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/error_handler.func)
+load_functions
+catch_errors
+
+# ==============================================================================
+# SECTION 2: NETWORK & CONNECTIVITY
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# verb_ip6()
+#
+# - Configures IPv6 based on DISABLEIPV6 variable
+# - If DISABLEIPV6=yes: disables IPv6 via sysctl
+# - Sets verbose mode via set_std_mode()
+# ------------------------------------------------------------------------------
+verb_ip6() {
+ set_std_mode # Set STD mode based on VERBOSE
+
+ if [ "$DISABLEIPV6" == "yes" ]; then
+ echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf
+ $STD sysctl -p
+ fi
+}
+
+# ------------------------------------------------------------------------------
+# setting_up_container()
+#
+# - Verifies network connectivity via hostname -I
+# - Retries up to RETRY_NUM times with RETRY_EVERY seconds delay
+# - Removes Python EXTERNALLY-MANAGED restrictions
+# - Disables systemd-networkd-wait-online.service for faster boot
+# - Exits with error if network unavailable after retries
+# ------------------------------------------------------------------------------
+setting_up_container() {
+ msg_info "Setting up Container OS"
+ for ((i = RETRY_NUM; i > 0; i--)); do
+ if [ "$(hostname -I)" != "" ]; then
+ break
+ fi
+ echo 1>&2 -en "${CROSS}${RD} No Network! "
+ sleep $RETRY_EVERY
+ done
+ if [ "$(hostname -I)" = "" ]; then
+ echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
+ echo -e "${NETWORK}Check Network Settings"
+ exit 1
+ fi
+ rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
+ systemctl disable -q --now systemd-networkd-wait-online.service
+ msg_ok "Set up Container OS"
+ #msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
+ msg_ok "Network Connected: ${BL}$(hostname -I)"
+}
+
+# ------------------------------------------------------------------------------
+# network_check()
+#
+# - Comprehensive network connectivity check for IPv4 and IPv6
+# - Tests connectivity to multiple DNS servers:
+# * IPv4: 1.1.1.1 (Cloudflare), 8.8.8.8 (Google), 9.9.9.9 (Quad9)
+# * IPv6: 2606:4700:4700::1111, 2001:4860:4860::8888, 2620:fe::fe
+# - Verifies DNS resolution for GitHub and Community-Scripts domains
+# - Prompts user to continue if no internet detected
+# - Uses fatal() on DNS resolution failure for critical hosts
+# ------------------------------------------------------------------------------
+network_check() {
+ set +e
+ trap - ERR
+ ipv4_connected=false
+ ipv6_connected=false
+ sleep 1
+
+ # Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
+ if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
+ msg_ok "IPv4 Internet Connected"
+ ipv4_connected=true
+ else
+ msg_error "IPv4 Internet Not Connected"
+ fi
+
+ # Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
+ if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
+ msg_ok "IPv6 Internet Connected"
+ ipv6_connected=true
+ else
+ msg_error "IPv6 Internet Not Connected"
+ fi
+
+ # If both IPv4 and IPv6 checks fail, prompt the user
+ if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
+ read -r -p "No Internet detected, would you like to continue anyway? " prompt
+ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
+ echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
+ else
+ echo -e "${NETWORK}Check Network Settings"
+ exit 1
+ fi
+ fi
+
+ # DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
+ GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
+ GIT_STATUS="Git DNS:"
+ DNS_FAILED=false
+
+ for HOST in "${GIT_HOSTS[@]}"; do
+ RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
+ if [[ -z "$RESOLVEDIP" ]]; then
+ GIT_STATUS+="$HOST:($DNSFAIL)"
+ DNS_FAILED=true
+ else
+ GIT_STATUS+=" $HOST:($DNSOK)"
+ fi
+ done
+
+ if [[ "$DNS_FAILED" == true ]]; then
+ fatal "$GIT_STATUS"
+ else
+ msg_ok "$GIT_STATUS"
+ fi
+
+ set -e
+ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
+}
+
+# ==============================================================================
+# SECTION 3: OS UPDATE & PACKAGE MANAGEMENT
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# update_os()
+#
+# - Updates container OS via apt-get update and dist-upgrade
+# - Configures APT cacher proxy if CACHER=yes (accelerates package downloads)
+# - Removes Python EXTERNALLY-MANAGED restrictions for pip
+# - Sources tools.func for additional setup functions after update
+# - Uses $STD wrapper to suppress output unless VERBOSE=yes
+# ------------------------------------------------------------------------------
+update_os() {
+ msg_info "Updating Container OS"
+ if [[ "$CACHER" == "yes" ]]; then
+ echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" >/etc/apt/apt.conf.d/00aptproxy
+ cat <<'EOF' >/usr/local/bin/apt-proxy-detect.sh
+#!/bin/bash
+if nc -w1 -z "${CACHER_IP}" 3142; then
+ echo -n "http://${CACHER_IP}:3142"
+else
+ echo -n "DIRECT"
+fi
+EOF
+ chmod +x /usr/local/bin/apt-proxy-detect.sh
+ fi
+ $STD apt-get update
+ $STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
+ rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
+ msg_ok "Updated Container OS"
+ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/tools.func)
+}
+
+# ==============================================================================
+# SECTION 4: MOTD & SSH CONFIGURATION
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# motd_ssh()
+#
+# - Configures Message of the Day (MOTD) with container information
+# - Creates /etc/profile.d/00_lxc-details.sh with:
+# * Application name
+# * Warning banner (DEV repository)
+# * OS name and version
+# * Hostname and IP address
+# * GitHub repository link
+# - Disables executable flag on /etc/update-motd.d/* scripts
+# - Enables root SSH access if SSH_ROOT=yes
+# - Configures TERM environment variable for better terminal support
+# ------------------------------------------------------------------------------
+motd_ssh() {
+ grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc
+
+ if [ -f "/etc/os-release" ]; then
+ OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
+ OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
+ elif [ -f "/etc/debian_version" ]; then
+ OS_NAME="Debian"
+ OS_VERSION=$(cat /etc/debian_version)
+ fi
+
+ PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
+ echo "echo -e \"\"" >"$PROFILE_FILE"
+ echo -e "echo -e \"${BOLD}${YW}${APPLICATION} LXC Container - DEV Repository${CL}\"" >>"$PROFILE_FILE"
+ echo -e "echo -e \"${RD}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL}\"" >>"$PROFILE_FILE"
+ echo -e "echo -e \"${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE"
+ echo -e "echo -e \"${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE"
+ echo -e "echo -e \"${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE"
+ echo -e "echo -e \"${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}\"" >>"$PROFILE_FILE"
+ echo "echo \"\"" >>"$PROFILE_FILE"
+
+ chmod -x /etc/update-motd.d/*
+
+ if [[ "${SSH_ROOT}" == "yes" ]]; then
+ sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
+ systemctl restart sshd
+ fi
+}
+
+# ==============================================================================
+# SECTION 5: CONTAINER CUSTOMIZATION
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# customize()
+#
+# - Customizes container for passwordless root login if PASSWORD is empty
+# - Configures getty for auto-login via /etc/systemd/system/container-getty@1.service.d/override.conf
+# - Creates /usr/bin/update script for easy application updates
+# - Injects SSH authorized keys if SSH_AUTHORIZED_KEY variable is set
+# - Sets proper permissions on SSH directories and key files
+# ------------------------------------------------------------------------------
+customize() {
+ if [[ "$PASSWORD" == "" ]]; then
+ msg_info "Customizing Container"
+ GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
+ mkdir -p $(dirname $GETTY_OVERRIDE)
+ cat <$GETTY_OVERRIDE
+ [Service]
+ ExecStart=
+ ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
+EOF
+ systemctl daemon-reload
+ systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
+ msg_ok "Customized Container"
+ fi
+ echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update
+ chmod +x /usr/bin/update
+ if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
+ mkdir -p /root/.ssh
+ echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
+ chmod 700 /root/.ssh
+ chmod 600 /root/.ssh/authorized_keys
+ fi
+}
diff --git a/misc/install.func b/misc/install.func
index 23cc293ad..ebe8078ac 100644
--- a/misc/install.func
+++ b/misc/install.func
@@ -28,17 +28,6 @@
# SECTION 1: INITIALIZATION
# ==============================================================================
-# Ensure INSTALL_LOG is set (exported from build.func, but fallback if missing)
-if [[ -z "${INSTALL_LOG:-}" ]]; then
- INSTALL_LOG="/root/.install-${SESSION_ID:-unknown}.log"
-fi
-
-# Dev mode: Persistent logs directory
-if [[ "${DEV_MODE_LOGS:-false}" == "true" ]]; then
- mkdir -p /var/log/community-scripts
- INSTALL_LOG="/var/log/community-scripts/install-${SESSION_ID:-unknown}-$(date +%Y%m%d_%H%M%S).log"
-fi
-
if ! command -v curl >/dev/null 2>&1; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1
@@ -49,9 +38,6 @@ source <(curl -fsSL https://raw.githubusercontent.com/luismco/ProxmoxVED/refs/he
load_functions
catch_errors
-# Re-parse dev_mode in container context (flags exported from host)
-parse_dev_mode
-
# ==============================================================================
# SECTION 2: NETWORK & CONNECTIVITY
# ==============================================================================
@@ -122,23 +108,20 @@ network_check() {
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
+ msg_ok "IPv4 Internet Connected"
ipv4_connected=true
- ipv4_status="${GN}✔${CL} IPv4"
else
- ipv4_status="${RD}✖${CL} IPv4"
+ msg_error "IPv4 Internet Not Connected"
fi
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
+ msg_ok "IPv6 Internet Connected"
ipv6_connected=true
- ipv6_status="${GN}✔${CL} IPv6"
else
- ipv6_status="${RD}✖${CL} IPv6"
+ msg_error "IPv6 Internet Not Connected"
fi
- # Show combined status
- msg_ok "Internet: ${ipv4_status} ${ipv6_status}"
-
# If both IPv4 and IPv6 checks fail, prompt the user
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
read -r -p "No Internet detected, would you like to continue anyway? " prompt
@@ -274,10 +257,10 @@ customize() {
msg_info "Customizing Container"
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
mkdir -p $(dirname $GETTY_OVERRIDE)
- cat <$GETTY_OVERRIDE
- [Service]
- ExecStart=
- ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
+ cat <<'EOF' >$GETTY_OVERRIDE
+[Service]
+ExecStart=
+ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 $TERM
EOF
systemctl daemon-reload
systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
diff --git a/misc/vm-core.func b/misc/vm-core.func
index 89cc1d716..099999de7 100644
--- a/misc/vm-core.func
+++ b/misc/vm-core.func
@@ -394,9 +394,9 @@ check_root() {
}
pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
echo -e "Exiting..."
sleep 2
exit
diff --git a/tools/addon/netdata.sh b/tools/addon/netdata.sh
index 1f2d598fa..cab0c8081 100644
--- a/tools/addon/netdata.sh
+++ b/tools/addon/netdata.sh
@@ -51,29 +51,29 @@ pve_check() {
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
# Proxmox VE 8.x: allow 8.0 – 8.9
- if [[ "$PVE_VER" =~ ^9\.([0-9]+)(\.[0-9]+)?$ ]]; then
+ if [[ "$PVE_VER" =~ ^8\.([0-9]+)(\.[0-9]+)?$ ]]; then
local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
+ if ((MINOR < 0 || MINOR > 9)); then
msg_error "Unsupported Proxmox VE version: $PVE_VER"
- msg_error "Supported versions: 8.0 – 8.9 or 9.0.x"
+ msg_error "Supported versions: 8.0 – 8.9 or 9.0 – 9.1"
exit 1
fi
return 0
fi
- # Proxmox VE 9.x: allow only 9.0
+ # Proxmox VE 9.x: allow 9.0 – 9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+)$ ]]; then
local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
+ if ((MINOR < 0 || MINOR > 1)); then
msg_error "Unsupported Proxmox VE version: $PVE_VER"
- msg_error "Supported versions: 8.0 – 8.9 or 9.0"
+ msg_error "Supported versions: 8.0 – 8.9 or 9.0 – 9.1"
exit 1
fi
return 0
fi
msg_error "Unsupported Proxmox VE version: $PVE_VER"
- msg_error "Supported versions: 8.0 – 8.9 or 9.0"
+ msg_error "Supported versions: 8.0 – 8.9 or 9.0 – 9.1"
exit 1
}
diff --git a/tools/addon/qbittorrent-exporter.sh b/tools/addon/qbittorrent-exporter.sh
new file mode 100644
index 000000000..29e1dff90
--- /dev/null
+++ b/tools/addon/qbittorrent-exporter.sh
@@ -0,0 +1,147 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: CrazyWolf13
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/core.func)
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/tools.func)
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+
+VERBOSE=${var_verbose:-no}
+APP="qbittorrent-exporter"
+APP_TYPE="tools"
+INSTALL_PATH="/opt/qbittorrent-exporter/src/qbittorrent-exporter"
+CONFIG_PATH="/opt/qbittorrent-exporter.env"
+header_info
+ensure_usr_local_bin_persist
+get_current_ip &>/dev/null
+
+# OS Detection
+if [[ -f "/etc/alpine-release" ]]; then
+ OS="Alpine"
+ SERVICE_PATH="/etc/init.d/qbittorrent-exporter"
+elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
+ OS="Debian"
+ SERVICE_PATH="/etc/systemd/system/qbittorrent-exporter.service"
+else
+ echo -e "${CROSS} Unsupported OS detected. Exiting."
+ exit 1
+fi
+
+# Existing installation
+if [[ -f "$INSTALL_PATH" ]]; then
+ echo -e "${YW}⚠️ qbittorrent-exporter is already installed.${CL}"
+ echo -n "Uninstall ${APP}? (y/N): "
+ read -r uninstall_prompt
+ if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
+ msg_info "Uninstalling qbittorrent-exporter"
+ if [[ "$OS" == "Debian" ]]; then
+ systemctl disable --now qbittorrent-exporter.service &>/dev/null
+ rm -f "$SERVICE_PATH"
+ else
+ rc-service qbittorrent-exporter stop &>/dev/null
+ rc-update del qbittorrent-exporter &>/dev/null
+ rm -f "$SERVICE_PATH"
+ fi
+ rm -f "$INSTALL_PATH" "$CONFIG_PATH" ~/.qbittorrent-exporter
+ msg_ok "${APP} has been uninstalled."
+ exit 0
+ fi
+
+ echo -n "Update qbittorrent-exporter? (y/N): "
+ read -r update_prompt
+ if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
+ if check_for_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter"; then
+ fetch_and_deploy_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter"
+ setup_go
+ msg_info "Updating qbittorrent-exporter"
+ cd /opt/qbittorrent-exporter/src
+ /usr/local/bin/go build -o ./qbittorrent-exporter
+ msg_ok "Updated Successfully!"
+ fi
+ exit 0
+ else
+ echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
+ exit 0
+ fi
+fi
+
+echo -e "${YW}⚠️ qbittorrent-exporter is not installed.${CL}"
+echo -n "Enter URL of qbittorrent example: (http://192.168.1.10:8080): "
+read -er QBITTORRENT_BASE_URL
+
+echo -n "Enter qbittorrent username: "
+read -er QBITTORRENT_USERNAME
+
+echo -n "Enter qbittorrent password: "
+read -rs QBITTORRENT_PASSWORD
+echo ""
+
+echo -n "Install qbittorrent-exporter? (y/n): "
+read -r install_prompt
+if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
+ echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
+ exit 0
+fi
+
+fetch_and_deploy_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter" "tarball" "v1.12.0"
+setup_go
+msg_info "Installing qbittorrent-exporter on ${OS}"
+cd /opt/qbittorrent-exporter/src
+/usr/local/bin/go build -o ./qbittorrent-exporter
+msg_ok "Installed qbittorrent-exporter"
+
+msg_info "Creating configuration"
+cat <"$CONFIG_PATH"
+QBITTORRENT_BASE_URL=${QBITTORRENT_BASE_URL}
+QBITTORRENT_USERNAME=${QBITTORRENT_USERNAME}
+QBITTORRENT_PASSWORD=${QBITTORRENT_PASSWORD}
+EOF
+msg_ok "Created configuration"
+
+msg_info "Creating service"
+if [[ "$OS" == "Debian" ]]; then
+ cat <"$SERVICE_PATH"
+[Unit]
+Description=qbittorrent-exporter
+After=network.target
+
+[Service]
+User=root
+WorkingDirectory=/opt/qbittorrent-exporter/src
+EnvironmentFile=$CONFIG_PATH
+ExecStart=/opt/qbittorrent-exporter/src/qbittorrent-exporter
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+EOF
+ systemctl enable --now qbittorrent-exporter &>/dev/null
+else
+ cat <"$SERVICE_PATH"
+#!/sbin/openrc-run
+
+command="$INSTALL_PATH"
+command_args=""
+command_background=true
+directory="/opt/qbittorrent-exporter/src"
+pidfile="/opt/qbittorrent-exporter/src/pidfile"
+
+depend() {
+ need net
+}
+
+start_pre() {
+ if [ -f "$CONFIG_PATH" ]; then
+ export \$(grep -v '^#' $CONFIG_PATH | xargs)
+ fi
+}
+EOF
+ chmod +x "$SERVICE_PATH"
+ rc-update add qbittorrent-exporter default &>/dev/null
+ rc-service qbittorrent-exporter start &>/dev/null
+fi
+msg_ok "Service created successfully"
+
+echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$CURRENT_IP:8090/metrics${CL}"
diff --git a/tools/headers/qbittorrent-exporter b/tools/headers/qbittorrent-exporter
new file mode 100644
index 000000000..07677b261
--- /dev/null
+++ b/tools/headers/qbittorrent-exporter
@@ -0,0 +1,6 @@
+ __ _ __ __ __ __
+ ____ _/ /_ (_) /_/ /_____ _____________ ____ / /_ ___ _ ______ ____ _____/ /____ _____
+ / __ `/ __ \/ / __/ __/ __ \/ ___/ ___/ _ \/ __ \/ __/_____/ _ \| |/_/ __ \/ __ \/ ___/ __/ _ \/ ___/
+/ /_/ / /_/ / / /_/ /_/ /_/ / / / / / __/ / / / /_/_____/ __/> /_/ / /_/ / / / /_/ __/ /
+\__, /_.___/_/\__/\__/\____/_/ /_/ \___/_/ /_/\__/ \___/_/|_/ .___/\____/_/ \__/\___/_/
+ /_/ /_/
diff --git a/vm/allstarlink-vm.sh b/vm/allstarlink-vm.sh
index 20d3e4786..0dc1bf3c0 100644
--- a/vm/allstarlink-vm.sh
+++ b/vm/allstarlink-vm.sh
@@ -8,8 +8,8 @@
source /dev/stdin <<<$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
___ ____ ____ __ __ _ __ _ ____ ___
/ | / / / ___// /_____ ______/ / (_)___ / /__ | | / / |/ /
/ /| | / / /\__ \/ __/ __ `/ ___/ / / / __ \/ //_/ | | / / /|_/ /
@@ -48,306 +48,306 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "${command}"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "${command}"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "AllStarLink VM" --yesno "This will create a New AllStarLink VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "⚠ User exited script \n" && exit
+ header_info && echo -e "⚠ User exited script \n" && exit
fi
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
- msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-3]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.3 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- if [ "$(dpkg --print-architecture)" != "arm64" ]; then
- msg_error "This script will not work with your CPU Architekture \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ if [ "$(dpkg --print-architecture)" != "arm64" ]; then
+ msg_error "This script will not work with your CPU Architekture \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
fi
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
fi
+ fi
}
function exit_script() {
- clear
- echo -e "⚠ User exited script \n"
- exit
+ clear
+ echo -e "⚠ User exited script \n"
+ exit
}
function default_settings() {
- VMID="$NEXTID"
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_CACHE=""
- HN="allstarlink"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
- echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${BL}Creating a AllStarLink VM using the above default settings${CL}"
+ VMID="$NEXTID"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_CACHE=""
+ HN="allstarlink"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${BL}Creating a AllStarLink VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $NEXTID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID="$NEXTID"
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
- else
- exit_script
- fi
- done
-
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
- else
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
- fi
+ METHOD="advanced"
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $NEXTID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID="$NEXTID"
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
else
- exit_script
+ exit_script
fi
+ done
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
- else
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
- fi
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
else
- exit_script
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
fi
+ else
+ exit_script
+ fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 allstarlink --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="allstarlink"
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
- else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
- fi
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
else
- exit_script
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
fi
+ else
+ exit_script
+ fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
- else
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
- fi
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 allstarlink --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="allstarlink"
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
else
- exit_script
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
fi
+ else
+ exit_script
+ fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
- else
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
- fi
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
else
- exit_script
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
fi
+ else
+ exit_script
+ fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="4096"
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
- else
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
- fi
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
else
- exit_script
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
fi
+ else
+ exit_script
+ fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
- else
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
- fi
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="4096"
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
else
- exit_script
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
fi
+ else
+ exit_script
+ fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
- else
- MAC="$MAC1"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
- fi
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
else
- exit_script
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
fi
+ else
+ exit_script
+ fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
- else
- VLAN=",tag=$VLAN1"
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
- fi
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
else
- exit_script
+ MAC="$MAC1"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
fi
+ else
+ exit_script
+ fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
- else
- MTU=",mtu=$MTU1"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
- fi
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
else
- exit_script
+ VLAN=",tag=$VLAN1"
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
fi
+ else
+ exit_script
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
else
- echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
+ MTU=",mtu=$MTU1"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
fi
+ else
+ exit_script
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a AllStarLink VM?" --no-button Do-Over 10 58); then
- echo -e "${RD}Creating a AllStarLink VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
+ else
+ echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
+ fi
+
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a AllStarLink VM?" --no-button Do-Over 10 58); then
+ echo -e "${RD}Creating a AllStarLink VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -359,29 +359,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -397,23 +397,23 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Installing Pre-Requisite libguestfs-tools onto Host"
@@ -422,41 +422,41 @@ msg_ok "Installed libguestfs-tools successfully"
msg_info "Adding ASL Package Repository"
virt-customize -q -a "${FILE}" \
- --run-command "curl -fsSL https://repo.allstarlink.org/public/asl-apt-repos.deb12_all.deb -o /tmp/asl-apt-repos.deb12_all.deb" \
- --run-command "dpkg -i /tmp/asl-apt-repos.deb12_all.deb" \
- --update \
- --run-command "rm -f /tmp/asl-apt-repos.deb12_all.deb" >/dev/null
+ --run-command "curl -fsSL https://repo.allstarlink.org/public/asl-apt-repos.deb12_all.deb -o /tmp/asl-apt-repos.deb12_all.deb" \
+ --run-command "dpkg -i /tmp/asl-apt-repos.deb12_all.deb" \
+ --update \
+ --run-command "rm -f /tmp/asl-apt-repos.deb12_all.deb" >/dev/null
msg_ok "Added ASL Package Repository"
msg_info "Installing AllStarLink (patience)"
virt-customize -q -a "${FILE}" \
- --install asl3 \
- --run-command "sed -i \"/secret /s/= .*/= $(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)/\" /etc/asterisk/manager.conf" >/dev/null
+ --install asl3 \
+ --run-command "sed -i \"/secret /s/= .*/= $(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)/\" /etc/asterisk/manager.conf" >/dev/null
msg_ok "Installed AllStarLink"
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Would you like to add Allmon3?" 10 58); then
- msg_info "Installing Allmon3"
- virt-customize -q -a "${FILE}" \
- --install allmon3 \
- --run-command "sed -i \"s/;pass=.*/;pass=\$(sed -ne 's/^secret = //p' /etc/asterisk/manager.conf)/\" /etc/allmon3/allmon3.ini" >/dev/null
- msg_ok "Installed Allmon3"
+ msg_info "Installing Allmon3"
+ virt-customize -q -a "${FILE}" \
+ --install allmon3 \
+ --run-command "sed -i \"s/;pass=.*/;pass=\$(sed -ne 's/^secret = //p' /etc/asterisk/manager.conf)/\" /etc/allmon3/allmon3.ini" >/dev/null
+ msg_ok "Installed Allmon3"
fi
msg_info "Creating a AllStarLink VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script,debian12,radio -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script,debian12,radio -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=2G \
- -boot order=scsi0 \
- -serial0 socket >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=2G \
+ -boot order=scsi0 \
+ -serial0 socket >/dev/null
qm resize $VMID scsi0 8G >/dev/null
qm set $VMID --agent enabled=1 >/dev/null
DESCRIPTION=$(
- cat <
@@ -489,9 +489,9 @@ qm set "$VMID" -description "$DESCRIPTION" >/dev/null
msg_ok "Created a AllStarLink VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting AllStarLink VM"
- qm start $VMID
- msg_ok "Started AllStarLink VM"
+ msg_info "Starting AllStarLink VM"
+ qm start $VMID
+ msg_ok "Started AllStarLink VM"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/archlinux-vm.sh b/vm/archlinux-vm.sh
index 28a2c256b..fa28e60b0 100644
--- a/vm/archlinux-vm.sh
+++ b/vm/archlinux-vm.sh
@@ -7,8 +7,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
___ __ __ _ _ ____ ___
/ | __________/ /_ / / (_)___ __ ___ __ | | / / |/ /
/ /| | / ___/ ___/ __ \ / / / / __ \/ / / / |/_/ | | / / /|_/ /
@@ -65,340 +65,340 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "${commad}"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "${commad}"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Arch Linux VM" --yesno "This will create a New Arch Linux VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_SIZE="4G"
- DISK_CACHE=""
- HN="arch-linux"
- CPU_TYPE=""
- CORE_COUNT="1"
- RAM_SIZE="1024"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_SIZE="4G"
+ DISK_CACHE=""
+ HN="arch-linux"
+ CPU_TYPE=""
+ CORE_COUNT="1"
+ RAM_SIZE="1024"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 arch-linux --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="arch-linux"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 arch-linux --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="arch-linux"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Arch Linux VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Arch Linux VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -410,29 +410,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -448,38 +448,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir | cifs)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a Arch Linux VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
- -ide2 ${STORAGE}:cloudinit \
- -boot order=scsi0 \
- -serial0 socket >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
+ -ide2 ${STORAGE}:cloudinit \
+ -boot order=scsi0 \
+ -serial0 socket >/dev/null
DESCRIPTION=$(
- cat <
@@ -510,18 +510,18 @@ EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
- msg_info "Resizing disk to $DISK_SIZE GB"
- qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
+ msg_info "Resizing disk to $DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
- msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
- qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
+ msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Arch Linux VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting Arch Linux VM"
- qm start $VMID
- msg_ok "Started Arch Linux VM"
+ msg_info "Starting Arch Linux VM"
+ qm start $VMID
+ msg_ok "Started Arch Linux VM"
fi
post_update_to_api "done" "none"
diff --git a/vm/debian-13-vm.sh b/vm/debian-13-vm.sh
index e1efe022a..7a2272972 100644
--- a/vm/debian-13-vm.sh
+++ b/vm/debian-13-vm.sh
@@ -7,8 +7,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
____ __ _ ________
/ __ \___ / /_ (_)___ _____ < /__ /
/ / / / _ \/ __ \/ / __ `/ __ \ / / /_ <
@@ -66,374 +66,374 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- post_update_to_api "failed" "${command}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ post_update_to_api "failed" "${command}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- post_update_to_api "done" "none"
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ post_update_to_api "done" "none"
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 13 VM" --yesno "This will create a New Debian 13 VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
-# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 (NOT 9.1+)
+# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 – 9.1
pve_check() {
- local PVE_VER
- PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
+ local PVE_VER
+ PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
- # Check for Proxmox VE 8.x: allow 8.0–8.9
- if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
- local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR < 0 || MINOR > 9)); then
- msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported: Proxmox VE version 8.0 – 8.9"
- exit 1
+ # Check for Proxmox VE 8.x: allow 8.0–8.9
+ if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
+ local MINOR="${BASH_REMATCH[1]}"
+ if ((MINOR < 0 || MINOR > 9)); then
+ msg_error "This version of Proxmox VE is not supported."
+ msg_error "Supported: Proxmox VE version 8.0 – 8.9"
+ exit 1
+ fi
+ return 0
fi
- return 0
- fi
- # Check for Proxmox VE 9.x: allow ONLY 9.0
- if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
- local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
- msg_error "This version of Proxmox VE is not yet supported."
- msg_error "Supported: Proxmox VE version 9.0"
- exit 1
+ # Check for Proxmox VE 9.x: allow 9.0–9.1
+ if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
+ local MINOR="${BASH_REMATCH[1]}"
+ if ((MINOR < 0 || MINOR > 1)); then
+ msg_error "This version of Proxmox VE is not yet supported."
+ msg_error "Supported: Proxmox VE version 9.0 – 9.1"
+ exit 1
+ fi
+ return 0
fi
- return 0
- fi
- # All other unsupported versions
- msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
- exit 1
+ # All other unsupported versions
+ msg_error "This version of Proxmox VE is not supported."
+ msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0 – 9.1"
+ exit 1
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=""
- MACHINE="q35"
- DISK_SIZE="30G"
- HN="debian"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="4096"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 13 VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=""
+ MACHINE="q35"
+ DISK_SIZE="30G"
+ HN="debian"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="4096"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 13 VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
+ "q35" "Modern (PCIe, UEFI, default)" ON \
+ "i440fx" "Legacy (older compatibility)" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ "$MACH" = "q35" ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
- "q35" "Modern (PCIe, UEFI, default)" ON \
- "i440fx" "Legacy (older compatibility)" OFF \
- 3>&1 1>&2 2>&3); then
- if [ "$MACH" = "q35" ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None" OFF \
+ "1" "Write Through (Default)" ON \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None" OFF \
- "1" "Write Through (Default)" ON \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="unifi-os-server"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="unifi-os-server"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 10 58 2 \
+ "KVM64" "Default – safe for migration/compatibility" ON \
+ "Host" "Use host CPU features (faster, no migration)" OFF \
+ 3>&1 1>&2 2>&3); then
+ case "$CPU_TYPE1" in
+ Host)
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ ;;
+ *)
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ ;;
+ esac
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 10 58 2 \
- "KVM64" "Default – safe for migration/compatibility" ON \
- "Host" "Use host CPU features (faster, no migration)" OFF \
- 3>&1 1>&2 2>&3); then
- case "$CPU_TYPE1" in
- Host)
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
- ;;
- *)
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
- ;;
- esac
- else
- exit-script
- fi
-
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" --yesno "Configure the VM with Cloud-init?" --defaultno 10 58); then
- echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}yes${CL}"
- CLOUD_INIT="yes"
- else
- echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}"
- CLOUD_INIT="no"
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" --yesno "Configure the VM with Cloud-init?" --defaultno 10 58); then
+ echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}yes${CL}"
+ CLOUD_INIT="yes"
+ else
+ echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}"
+ CLOUD_INIT="no"
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
+ else
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Debian 13 VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 13 VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Debian 13 VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 13 VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
arch_check
@@ -444,40 +444,40 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
- printf "\e[?25h"
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
+ printf "\e[?25h"
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
msg_info "Retrieving the URL for the Debian 13 Qcow2 Disk Image"
if [ "$CLOUD_INIT" == "yes" ]; then
- URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2
+ URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2
else
- URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-nocloud-amd64.qcow2
+ URL=https://cloud.debian.org/images/cloud/trixie/latest/debian-13-nocloud-amd64.qcow2
fi
CACHE_DIR="/var/lib/vz/template/cache"
CACHE_FILE="$CACHE_DIR/$(basename "$URL")"
@@ -486,49 +486,49 @@ mkdir -p "$CACHE_DIR" "$(dirname "$FILE_IMG")"
msg_ok "${CL}${BL}${URL}${CL}"
if [[ ! -s "$CACHE_FILE" ]]; then
- curl -f#SL -o "$CACHE_FILE" "$URL"
- msg_ok "Downloaded ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
+ curl -f#SL -o "$CACHE_FILE" "$URL"
+ msg_ok "Downloaded ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
else
- msg_ok "Using cached image ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
+ msg_ok "Using cached image ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
fi
set -o pipefail
msg_info "Creating Debian 13 VM shell"
qm create "$VMID" -machine q35 -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
- -cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" -tags community-script \
- -net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
+ -cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" -tags community-script \
+ -net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
msg_ok "Created VM shell"
msg_info "Importing disk into storage ($STORAGE)"
if qm disk import --help >/dev/null 2>&1; then
- IMPORT_CMD=(qm disk import)
+ IMPORT_CMD=(qm disk import)
else
- IMPORT_CMD=(qm importdisk)
+ IMPORT_CMD=(qm importdisk)
fi
IMPORT_OUT="$("${IMPORT_CMD[@]}" "$VMID" "$CACHE_FILE" "$STORAGE" --format raw 2>&1 || true)"
DISK_REF="$(printf '%s\n' "$IMPORT_OUT" | sed -n "s/.*successfully imported disk '\([^']\+\)'.*/\1/p" | tr -d "\r\"'")"
[[ -z "$DISK_REF" ]] && DISK_REF="$(pvesm list "$STORAGE" | awk -v id="$VMID" '$5 ~ ("vm-"id"-disk-") {print $1":"$5}' | sort | tail -n1)"
[[ -z "$DISK_REF" ]] && {
- msg_error "Unable to determine imported disk reference."
- echo "$IMPORT_OUT"
- exit 1
+ msg_error "Unable to determine imported disk reference."
+ echo "$IMPORT_OUT"
+ exit 1
}
msg_ok "Imported disk (${CL}${BL}${DISK_REF}${CL})"
msg_info "Attaching EFI and root disk"
if [ "$CLOUD_INIT" == "yes" ]; then
- qm set "$VMID" \
- --efidisk0 "${STORAGE}:0,efitype=4m" \
- --scsi0 "${DISK_REF},ssd=1,discard=on" \
- --scsi1 "${STORAGE}:cloudinit" \
- --boot order=scsi0 \
- --serial0 socket >/dev/null
+ qm set "$VMID" \
+ --efidisk0 "${STORAGE}:0,efitype=4m" \
+ --scsi0 "${DISK_REF},ssd=1,discard=on" \
+ --scsi1 "${STORAGE}:cloudinit" \
+ --boot order=scsi0 \
+ --serial0 socket >/dev/null
else
- qm set "$VMID" \
- --efidisk0 "${STORAGE}:0,efitype=4m" \
- --scsi0 "${DISK_REF},ssd=1,discard=on" \
- --boot order=scsi0 \
- --serial0 socket >/dev/null
+ qm set "$VMID" \
+ --efidisk0 "${STORAGE}:0,efitype=4m" \
+ --scsi0 "${DISK_REF},ssd=1,discard=on" \
+ --boot order=scsi0 \
+ --serial0 socket >/dev/null
fi
qm set "$VMID" --agent enabled=1 >/dev/null
msg_ok "Attached EFI and root disk"
@@ -538,7 +538,7 @@ qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
msg_ok "Resized disk"
DESCRIPTION=$(
- cat <
@@ -571,9 +571,9 @@ qm set "$VMID" -description "$DESCRIPTION" >/dev/null
msg_ok "Created a Debian 13 VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting Debian 13 VM"
- qm start $VMID
- msg_ok "Started Debian 13 VM"
+ msg_info "Starting Debian 13 VM"
+ qm start $VMID
+ msg_ok "Started Debian 13 VM"
fi
msg_info "Installing resize tools in VM"
diff --git a/vm/docker-vm-debug.sh b/vm/docker-vm-debug.sh
index 861aa6976..6da5ec333 100644
--- a/vm/docker-vm-debug.sh
+++ b/vm/docker-vm-debug.sh
@@ -161,7 +161,7 @@ function check_root() {
}
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
-# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 (NOT 9.1+)
+# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 – 9.1
pve_check() {
local PVE_VER
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
@@ -178,12 +178,12 @@ pve_check() {
return 0
fi
- # Check for Proxmox VE 9.x: allow ONLY 9.0
+ # Check for Proxmox VE 9.x: allow 9.0 – 9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
+ if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported."
- msg_error "Supported: Proxmox VE version 9.0"
+ msg_error "Supported: Proxmox VE version 9.0 – 9.1"
exit 1
fi
PVE_MAJOR=9
@@ -192,7 +192,7 @@ pve_check() {
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
+ msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0 – 9.1"
exit 1
}
diff --git a/vm/docker-vm.sh b/vm/docker-vm.sh
index 6714582a0..68dc581e2 100644
--- a/vm/docker-vm.sh
+++ b/vm/docker-vm.sh
@@ -29,7 +29,7 @@ var_os="debian"
var_version="13"
DISK_SIZE="10G"
USE_CLOUD_INIT="no"
-INSTALL_PORTAINER="no"
+# INSTALL_PORTAINER="no"
OS_TYPE=""
OS_VERSION=""
@@ -161,7 +161,7 @@ function check_root() {
}
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
-# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 (NOT 9.1+)
+# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 – 9.1
pve_check() {
local PVE_VER
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
@@ -178,12 +178,12 @@ pve_check() {
return 0
fi
- # Check for Proxmox VE 9.x: allow ONLY 9.0
+ # Check for Proxmox VE 9.x: allow 9.0–9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
+ if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported."
- msg_error "Supported: Proxmox VE version 9.0"
+ msg_error "Supported: Proxmox VE version 9.0 – 9.1"
exit 1
fi
PVE_MAJOR=9
@@ -192,7 +192,7 @@ pve_check() {
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
+ msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0 – 9.1"
exit 1
}
@@ -284,16 +284,16 @@ function select_cloud_init() {
fi
}
-function select_portainer() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "PORTAINER" \
- --yesno "Install Portainer for Docker management?\n\nPortainer is a lightweight management UI for Docker.\n\nAccess after installation:\n• HTTP: http://:9000\n• HTTPS: https://:9443" 14 68); then
- INSTALL_PORTAINER="yes"
- echo -e "${ADVANCED}${BOLD}${DGN}Portainer: ${BGN}yes${CL}"
- else
- INSTALL_PORTAINER="no"
- echo -e "${ADVANCED}${BOLD}${DGN}Portainer: ${BGN}no${CL}"
- fi
-}
+# function select_portainer() {
+# if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "PORTAINER" \
+# --yesno "Install Portainer for Docker management?\n\nPortainer is a lightweight management UI for Docker.\n\nAccess after installation:\n• HTTP: http://:9000\n• HTTPS: https://:9443" 14 68); then
+# INSTALL_PORTAINER="yes"
+# echo -e "${ADVANCED}${BOLD}${DGN}Portainer: ${BGN}yes${CL}"
+# else
+# INSTALL_PORTAINER="no"
+# echo -e "${ADVANCED}${BOLD}${DGN}Portainer: ${BGN}no${CL}"
+# fi
+# }
function get_image_url() {
local arch=$(dpkg --print-architecture)
@@ -323,7 +323,7 @@ function default_settings() {
select_cloud_init
# Portainer Selection - ALWAYS ask
- select_portainer
+ # select_portainer
# Set defaults for other settings
VMID=$(get_valid_nextid)
@@ -367,7 +367,7 @@ function advanced_settings() {
select_cloud_init
# Portainer Selection - ALWAYS ask (at the beginning)
- select_portainer
+ # select_portainer
METHOD="advanced"
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
@@ -703,7 +703,7 @@ for i in {1..10}; do
done
# Install Portainer if requested
-INSTALL_PORTAINER_PLACEHOLDER
+# INSTALL_PORTAINER_PLACEHOLDER
# Create completion flag
echo \"[\\$(date)] Docker installation completed successfully\"
@@ -711,20 +711,20 @@ touch /root/.docker-installed
INSTALLEOF" >/dev/null
# Add Portainer installation script if requested
-if [ "$INSTALL_PORTAINER" = "yes" ]; then
- virt-customize -q -a "${FILE}" --run-command "cat > /root/install-portainer.sh << 'PORTAINEREOF'
-#!/bin/bash
-exec >> /var/log/install-docker.log 2>&1
-echo \"[\\$(date)] Installing Portainer\"
-docker volume create portainer_data
-docker run -d -p 9000:9000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
-echo \"[\\$(date)] Portainer installed and started\"
-PORTAINEREOF" >/dev/null
- virt-customize -q -a "${FILE}" --run-command "chmod +x /root/install-portainer.sh" >/dev/null
- virt-customize -q -a "${FILE}" --run-command "sed -i 's|INSTALL_PORTAINER_PLACEHOLDER|/root/install-portainer.sh|' /root/install-docker.sh" >/dev/null
-else
- virt-customize -q -a "${FILE}" --run-command "sed -i 's|INSTALL_PORTAINER_PLACEHOLDER|echo \"[\\\\\\$(date)] Skipping Portainer installation\"|' /root/install-docker.sh" >/dev/null
-fi
+# if [ "$INSTALL_PORTAINER" = "yes" ]; then
+# virt-customize -q -a "${FILE}" --run-command "cat > /root/install-portainer.sh << 'PORTAINEREOF'
+# #!/bin/bash
+# exec >> /var/log/install-docker.log 2>&1
+# echo \"[\\$(date)] Installing Portainer\"
+# docker volume create portainer_data
+# docker run -d -p 9000:9000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
+# echo \"[\\$(date)] Portainer installed and started\"
+# PORTAINEREOF" >/dev/null
+# virt-customize -q -a "${FILE}" --run-command "chmod +x /root/install-portainer.sh" >/dev/null
+# virt-customize -q -a "${FILE}" --run-command "sed -i 's|INSTALL_PORTAINER_PLACEHOLDER|/root/install-portainer.sh|' /root/install-docker.sh" >/dev/null
+# else
+# virt-customize -q -a "${FILE}" --run-command "sed -i 's|INSTALL_PORTAINER_PLACEHOLDER|echo \"[\\\\\\$(date)] Skipping Portainer installation\"|' /root/install-docker.sh" >/dev/null
+# fi
virt-customize -q -a "${FILE}" --run-command "chmod +x /root/install-docker.sh" >/dev/null
@@ -899,15 +899,15 @@ else
echo -e "${TAB}${DGN}Docker: ${BGN}Latest (via get.docker.com)${CL}"
fi
-if [ "$INSTALL_PORTAINER" = "yes" ]; then
- if [ -n "$VM_IP" ]; then
- echo -e "${TAB}${DGN}Portainer: ${BGN}https://${VM_IP}:9443${CL}"
- else
- echo -e "${TAB}${DGN}Portainer: ${BGN}Will be accessible at https://:9443${CL}"
- echo -e "${TAB}${YW}⚠️ Wait 2-3 minutes after boot for installation to complete${CL}"
- echo -e "${TAB}${YW}⚠️ Get IP with: ${BL}qm guest cmd ${VMID} network-get-interfaces${CL}"
- fi
-fi
+# if [ "$INSTALL_PORTAINER" = "yes" ]; then
+# if [ -n "$VM_IP" ]; then
+# echo -e "${TAB}${DGN}Portainer: ${BGN}https://${VM_IP}:9443${CL}"
+# else
+# echo -e "${TAB}${DGN}Portainer: ${BGN}Will be accessible at https://:9443${CL}"
+# echo -e "${TAB}${YW}⚠️ Wait 2-3 minutes after boot for installation to complete${CL}"
+# echo -e "${TAB}${YW}⚠️ Get IP with: ${BL}qm guest cmd ${VMID} network-get-interfaces${CL}"
+# fi
+# fi
if [ "$USE_CLOUD_INIT" = "yes" ]; then
display_cloud_init_info "$VMID" "$HN"
fi
diff --git a/vm/nextcloud-vm.sh b/vm/nextcloud-vm.sh
index d67102593..083534c3f 100644
--- a/vm/nextcloud-vm.sh
+++ b/vm/nextcloud-vm.sh
@@ -8,12 +8,12 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
______ __ __ _ __ __ __ __ _ ____ ___
/_ __/_ _________ / //_/__ __ __ / |/ /____ __/ /_____/ /__ __ _____/ / | | / / |/ /
- / / / // / __/ _ \/ ,< / -_) // / / / -_) \ / __/ __/ / _ \/ // / _ / | |/ / /|_/ /
-/_/ \_,_/_/ /_//_/_/|_|\__/\_, / /_/|_/\__/_\_\\__/\__/_/\___/\_,_/\_,_/ |___/_/ /_/
+ / / / // / __/ _ \/ ,< / -_) // / / / -_) \ / __/ __/ / _ \/ // / _ / | |/ / /|_/ /
+/_/ \_,_/_/ /_//_/_/|_|\__/\_, / /_/|_/\__/_\_\\__/\__/_/\___/\_,_/\_,_/ |___/_/ /_/
/___/
EOF
}
@@ -46,322 +46,322 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "${command}"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "${command}"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "⚠ User exited script \n" && exit
+ header_info && echo -e "⚠ User exited script \n" && exit
fi
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- msg_error "This script will not work with PiMox! \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ msg_error "This script will not work with PiMox! \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "⚠ User exited script \n"
- exit
+ clear
+ echo -e "⚠ User exited script \n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_CACHE=""
- HN="turnkey-nextcloud-vm"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="no"
- METHOD="default"
- echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
- echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
- echo -e "${BL}Creating a $NAME using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_CACHE=""
+ HN="turnkey-nextcloud-vm"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="no"
+ METHOD="default"
+ echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
+ echo -e "${BL}Creating a $NAME using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-nextcloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="$HN"
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-nextcloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="$HN"
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
- echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
+ echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -374,29 +374,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -412,38 +412,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1,2}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a $NAME"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
- -scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
- -boot order='scsi1;scsi0' >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
+ -scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
+ -boot order='scsi1;scsi0' >/dev/null
DESCRIPTION=$(
- cat <
@@ -456,7 +456,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -476,9 +476,9 @@ qm set "$VMID" -description "$DESCRIPTION" >/dev/null
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting $NAME"
- qm start $VMID
- msg_ok "Started $NAME"
+ msg_info "Starting $NAME"
+ qm start $VMID
+ msg_ok "Started $NAME"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/openwrt.sh b/vm/openwrt.sh
index 86f6e4e4f..d5c8a0f38 100644
--- a/vm/openwrt.sh
+++ b/vm/openwrt.sh
@@ -10,8 +10,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
____ _ __ __
/ __ \____ ___ ____| | / /____/ /_
/ / / / __ \/ _ \/ __ \ | /| / / ___/ __/
@@ -50,380 +50,380 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
function send_line_to_vm() {
- echo -e "${DGN}Sending line: ${YW}$1${CL}"
- for ((i = 0; i < ${#1}; i++)); do
- character=${1:i:1}
- case $character in
- " ") character="spc" ;;
- "-") character="minus" ;;
- "=") character="equal" ;;
- ",") character="comma" ;;
- ".") character="dot" ;;
- "/") character="slash" ;;
- "'") character="apostrophe" ;;
- ";") character="semicolon" ;;
- '\') character="backslash" ;;
- '`') character="grave_accent" ;;
- "[") character="bracket_left" ;;
- "]") character="bracket_right" ;;
- "_") character="shift-minus" ;;
- "+") character="shift-equal" ;;
- "?") character="shift-slash" ;;
- "<") character="shift-comma" ;;
- ">") character="shift-dot" ;;
- '"') character="shift-apostrophe" ;;
- ":") character="shift-semicolon" ;;
- "|") character="shift-backslash" ;;
- "~") character="shift-grave_accent" ;;
- "{") character="shift-bracket_left" ;;
- "}") character="shift-bracket_right" ;;
- "A") character="shift-a" ;;
- "B") character="shift-b" ;;
- "C") character="shift-c" ;;
- "D") character="shift-d" ;;
- "E") character="shift-e" ;;
- "F") character="shift-f" ;;
- "G") character="shift-g" ;;
- "H") character="shift-h" ;;
- "I") character="shift-i" ;;
- "J") character="shift-j" ;;
- "K") character="shift-k" ;;
- "L") character="shift-l" ;;
- "M") character="shift-m" ;;
- "N") character="shift-n" ;;
- "O") character="shift-o" ;;
- "P") character="shift-p" ;;
- "Q") character="shift-q" ;;
- "R") character="shift-r" ;;
- "S") character="shift-s" ;;
- "T") character="shift-t" ;;
- "U") character="shift-u" ;;
- "V") character="shift-v" ;;
- "W") character="shift-w" ;;
- "X") character="shift=x" ;;
- "Y") character="shift-y" ;;
- "Z") character="shift-z" ;;
- "!") character="shift-1" ;;
- "@") character="shift-2" ;;
- "#") character="shift-3" ;;
- '$') character="shift-4" ;;
- "%") character="shift-5" ;;
- "^") character="shift-6" ;;
- "&") character="shift-7" ;;
- "*") character="shift-8" ;;
- "(") character="shift-9" ;;
- ")") character="shift-0" ;;
- esac
- qm sendkey $VMID "$character"
- done
- qm sendkey $VMID ret
+ echo -e "${DGN}Sending line: ${YW}$1${CL}"
+ for ((i = 0; i < ${#1}; i++)); do
+ character=${1:i:1}
+ case $character in
+ " ") character="spc" ;;
+ "-") character="minus" ;;
+ "=") character="equal" ;;
+ ",") character="comma" ;;
+ ".") character="dot" ;;
+ "/") character="slash" ;;
+ "'") character="apostrophe" ;;
+ ";") character="semicolon" ;;
+ '\') character="backslash" ;;
+ '`') character="grave_accent" ;;
+ "[") character="bracket_left" ;;
+ "]") character="bracket_right" ;;
+ "_") character="shift-minus" ;;
+ "+") character="shift-equal" ;;
+ "?") character="shift-slash" ;;
+ "<") character="shift-comma" ;;
+ ">") character="shift-dot" ;;
+ '"') character="shift-apostrophe" ;;
+ ":") character="shift-semicolon" ;;
+ "|") character="shift-backslash" ;;
+ "~") character="shift-grave_accent" ;;
+ "{") character="shift-bracket_left" ;;
+ "}") character="shift-bracket_right" ;;
+ "A") character="shift-a" ;;
+ "B") character="shift-b" ;;
+ "C") character="shift-c" ;;
+ "D") character="shift-d" ;;
+ "E") character="shift-e" ;;
+ "F") character="shift-f" ;;
+ "G") character="shift-g" ;;
+ "H") character="shift-h" ;;
+ "I") character="shift-i" ;;
+ "J") character="shift-j" ;;
+ "K") character="shift-k" ;;
+ "L") character="shift-l" ;;
+ "M") character="shift-m" ;;
+ "N") character="shift-n" ;;
+ "O") character="shift-o" ;;
+ "P") character="shift-p" ;;
+ "Q") character="shift-q" ;;
+ "R") character="shift-r" ;;
+ "S") character="shift-s" ;;
+ "T") character="shift-t" ;;
+ "U") character="shift-u" ;;
+ "V") character="shift-v" ;;
+ "W") character="shift-w" ;;
+ "X") character="shift=x" ;;
+ "Y") character="shift-y" ;;
+ "Z") character="shift-z" ;;
+ "!") character="shift-1" ;;
+ "@") character="shift-2" ;;
+ "#") character="shift-3" ;;
+ '$') character="shift-4" ;;
+ "%") character="shift-5" ;;
+ "^") character="shift-6" ;;
+ "&") character="shift-7" ;;
+ "*") character="shift-8" ;;
+ "(") character="shift-9" ;;
+ ")") character="shift-0" ;;
+ esac
+ qm sendkey $VMID "$character"
+ done
+ qm sendkey $VMID ret
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "OpenWrt VM" --yesno "This will create a New OpenWrt VM. Proceed?" 10 58); then
- :
+ :
else
- header_info && echo -e "⚠ User exited script \n" && exit
+ header_info && echo -e "⚠ User exited script \n" && exit
fi
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}"
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${CROSS} This script will not work with PiMox! \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${CROSS} This script will not work with PiMox! \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "⚠ User exited script \n"
- exit
+ clear
+ echo -e "⚠ User exited script \n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- HN=openwrt
- CORE_COUNT="1"
- RAM_SIZE="256"
- BRG="vmbr0"
- VLAN=""
- MAC=$GEN_MAC
- LAN_MAC=$GEN_MAC_LAN
- LAN_BRG="vmbr0"
- LAN_IP_ADDR="192.168.1.1"
- LAN_NETMASK="255.255.255.0"
- LAN_VLAN=",tag=999"
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
- echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${DGN}Using WAN Bridge: ${BGN}${BRG}${CL}"
- echo -e "${DGN}Using WAN VLAN: ${BGN}Default${CL}"
- echo -e "${DGN}Using WAN MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${DGN}Using LAN MAC Address: ${BGN}${LAN_MAC}${CL}"
- echo -e "${DGN}Using LAN Bridge: ${BGN}${LAN_BRG}${CL}"
- echo -e "${DGN}Using LAN VLAN: ${BGN}999${CL}"
- echo -e "${DGN}Using LAN IP Address: ${BGN}${LAN_IP_ADDR}${CL}"
- echo -e "${DGN}Using LAN NETMASK: ${BGN}${LAN_NETMASK}${CL}"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${BL}Creating a OpenWrt VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ HN=openwrt
+ CORE_COUNT="1"
+ RAM_SIZE="256"
+ BRG="vmbr0"
+ VLAN=""
+ MAC=$GEN_MAC
+ LAN_MAC=$GEN_MAC_LAN
+ LAN_BRG="vmbr0"
+ LAN_IP_ADDR="192.168.1.1"
+ LAN_NETMASK="255.255.255.0"
+ LAN_VLAN=",tag=999"
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
+ echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${DGN}Using WAN Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${DGN}Using WAN VLAN: ${BGN}Default${CL}"
+ echo -e "${DGN}Using WAN MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${DGN}Using LAN MAC Address: ${BGN}${LAN_MAC}${CL}"
+ echo -e "${DGN}Using LAN Bridge: ${BGN}${LAN_BRG}${CL}"
+ echo -e "${DGN}Using LAN VLAN: ${BGN}999${CL}"
+ echo -e "${DGN}Using LAN IP Address: ${BGN}${LAN_IP_ADDR}${CL}"
+ echo -e "${DGN}Using LAN NETMASK: ${BGN}${LAN_NETMASK}${CL}"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${BL}Creating a OpenWrt VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 openwrt --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="openwrt"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ fi
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
else
- exit-script
+ exit-script
fi
- done
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 openwrt --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="openwrt"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 1 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="1"
+ fi
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ exit-script
fi
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 1 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="1"
- fi
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
- else
- exit-script
- fi
-
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 256 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="256"
- fi
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
- else
- exit-script
- fi
-
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr0 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- fi
- echo -e "${DGN}Using WAN Bridge: ${BGN}$BRG${CL}"
- else
- exit-script
- fi
-
- if LAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $LAN_BRG ]; then
- LAN_BRG="vmbr0"
- fi
- echo -e "${DGN}Using LAN Bridge: ${BGN}$LAN_BRG${CL}"
- else
- exit-script
- fi
-
- if LAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router IP" 8 58 $LAN_IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $LAN_IP_ADDR ]; then
- LAN_IP_ADDR="192.168.1.1"
- fi
- echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$LAN_IP_ADDR${CL}"
- else
- exit-script
- fi
-
- if LAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router netmask" 8 58 $LAN_NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $LAN_NETMASK ]; then
- LAN_NETMASK="255.255.255.0"
- fi
- echo -e "${DGN}Using LAN NETMASK: ${BGN}$LAN_NETMASK${CL}"
- else
- exit-script
- fi
-
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 256 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="256"
+ fi
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
else
- MAC="$MAC1"
+ exit-script
fi
- echo -e "${DGN}Using WAN MAC Address: ${BGN}$MAC${CL}"
- else
- exit-script
- fi
- if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC2 ]; then
- LAN_MAC="$GEN_MAC_LAN"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr0 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ fi
+ echo -e "${DGN}Using WAN Bridge: ${BGN}$BRG${CL}"
else
- LAN_MAC="$MAC2"
+ exit-script
fi
- echo -e "${DGN}Using LAN MAC Address: ${BGN}$LAN_MAC${CL}"
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Vlan (leave blank for default)" 8 58 --title "WAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
+ if LAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $LAN_BRG ]; then
+ LAN_BRG="vmbr0"
+ fi
+ echo -e "${DGN}Using LAN Bridge: ${BGN}$LAN_BRG${CL}"
else
- VLAN=",tag=$VLAN1"
+ exit-script
fi
- echo -e "${DGN}Using WAN Vlan: ${BGN}$VLAN1${CL}"
- else
- exit-script
- fi
- if VLAN2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Vlan" 8 58 999 --title "LAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN2 ]; then
- VLAN2="999"
- LAN_VLAN=",tag=$VLAN2"
+ if LAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router IP" 8 58 $LAN_IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $LAN_IP_ADDR ]; then
+ LAN_IP_ADDR="192.168.1.1"
+ fi
+ echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$LAN_IP_ADDR${CL}"
else
- LAN_VLAN=",tag=$VLAN2"
+ exit-script
fi
- echo -e "${DGN}Using LAN Vlan: ${BGN}$VLAN2${CL}"
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
+ if LAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a router netmask" 8 58 $LAN_NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $LAN_NETMASK ]; then
+ LAN_NETMASK="255.255.255.0"
+ fi
+ echo -e "${DGN}Using LAN NETMASK: ${BGN}$LAN_NETMASK${CL}"
else
- MTU=",mtu=$MTU1"
+ exit-script
fi
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- START_VM="yes"
- else
- START_VM="no"
- fi
- echo -e "${DGN}Start VM when completed: ${BGN}$START_VM${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ else
+ MAC="$MAC1"
+ fi
+ echo -e "${DGN}Using WAN MAC Address: ${BGN}$MAC${CL}"
+ else
+ exit-script
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OpenWrt VM?" --no-button Do-Over 10 58); then
- echo -e "${RD}Creating a OpenWrt VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC2 ]; then
+ LAN_MAC="$GEN_MAC_LAN"
+ else
+ LAN_MAC="$MAC2"
+ fi
+ echo -e "${DGN}Using LAN MAC Address: ${BGN}$LAN_MAC${CL}"
+ else
+ exit-script
+ fi
+
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Vlan (leave blank for default)" 8 58 --title "WAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ else
+ VLAN=",tag=$VLAN1"
+ fi
+ echo -e "${DGN}Using WAN Vlan: ${BGN}$VLAN1${CL}"
+ else
+ exit-script
+ fi
+
+ if VLAN2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Vlan" 8 58 999 --title "LAN VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN2 ]; then
+ VLAN2="999"
+ LAN_VLAN=",tag=$VLAN2"
+ else
+ LAN_VLAN=",tag=$VLAN2"
+ fi
+ echo -e "${DGN}Using LAN Vlan: ${BGN}$VLAN2${CL}"
+ else
+ exit-script
+ fi
+
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ else
+ MTU=",mtu=$MTU1"
+ fi
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ exit-script
+ fi
+
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ START_VM="yes"
+ else
+ START_VM="no"
+ fi
+ echo -e "${DGN}Start VM when completed: ${BGN}$START_VM${CL}"
+
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OpenWrt VM?" --no-button Do-Over 10 58); then
+ echo -e "${RD}Creating a OpenWrt VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
arch_check
@@ -434,30 +434,30 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- echo -e "\n${RD}⚠ Unable to detect a valid storage location.${CL}"
- echo -e "Exiting..."
- exit
+ echo -e "\n${RD}⚠ Unable to detect a valid storage location.${CL}"
+ echo -e "Exiting..."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for the OpenWrt VM?\n\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for the OpenWrt VM?\n\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -482,35 +482,35 @@ msg_ok "Extracted & Resized OpenWrt Disk Image ${CL}${BL}$FILE${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating OpenWrt VM"
qm create $VMID -cores $CORE_COUNT -memory $RAM_SIZE -name $HN \
- -onboot 1 -ostype l26 -scsihw virtio-scsi-pci --tablet 0
+ -onboot 1 -ostype l26 -scsihw virtio-scsi-pci --tablet 0
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE%.*} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF},efitype=4m,size=4M \
- -scsi0 ${DISK1_REF},size=512M \
- -boot order=scsi0 \
- -tags community-script >/dev/null
+ -efidisk0 ${DISK0_REF},efitype=4m,size=4M \
+ -scsi0 ${DISK1_REF},size=512M \
+ -boot order=scsi0 \
+ -tags community-script >/dev/null
DESCRIPTION=$(
- cat <
@@ -523,7 +523,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -561,21 +561,21 @@ send_line_to_vm "uci commit"
send_line_to_vm "halt"
msg_ok "Network interfaces have been successfully configured."
until qm status $VMID | grep -q "stopped"; do
- sleep 2
+ sleep 2
done
msg_info "Bridge interfaces are being added."
qm set $VMID \
- -net0 virtio,bridge=${LAN_BRG},macaddr=${LAN_MAC}${LAN_VLAN}${MTU} \
- -net1 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} >/dev/null 2>/dev/null
+ -net0 virtio,bridge=${LAN_BRG},macaddr=${LAN_MAC}${LAN_VLAN}${MTU} \
+ -net1 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} >/dev/null 2>/dev/null
msg_ok "Bridge interfaces have been successfully added."
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting OpenWrt VM"
- qm start $VMID
- msg_ok "Started OpenWrt VM"
+ msg_info "Starting OpenWrt VM"
+ qm start $VMID
+ msg_ok "Started OpenWrt VM"
fi
VLAN_FINISH=""
if [ "$VLAN" == "" ] && [ "$VLAN2" != "999" ]; then
- VLAN_FINISH=" Please remember to adjust the VLAN tags to suit your network."
+ VLAN_FINISH=" Please remember to adjust the VLAN tags to suit your network."
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n${VLAN_FINISH}"
diff --git a/vm/opnsense-vm.sh b/vm/opnsense-vm.sh
index ff2c2aac7..156fb913d 100644
--- a/vm/opnsense-vm.sh
+++ b/vm/opnsense-vm.sh
@@ -7,14 +7,14 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
- ____ ____ _ __
- / __ \/ __ \/ | / /_______ ____ ________
+ clear
+ cat <<"EOF"
+ ____ ____ _ __
+ / __ \/ __ \/ | / /_______ ____ ________
/ / / / /_/ / |/ / ___/ _ \/ __ \/ ___/ _ \
/ /_/ / ____/ /| (__ ) __/ / / (__ ) __/
-\____/_/ /_/ |_/____/\___/_/ /_/____/\___/
-
+\____/_/ /_/ |_/____/\___/_/ /_/____/\___/
+
EOF
}
header_info
@@ -45,466 +45,466 @@ set -Eeo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- post_update_to_api "done" "none"
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ post_update_to_api "done" "none"
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
function send_line_to_vm() {
- echo -e "${DGN}Sending line: ${YW}$1${CL}"
- for ((i = 0; i < ${#1}; i++)); do
- character=${1:i:1}
- case $character in
- " ") character="spc" ;;
- "-") character="minus" ;;
- "=") character="equal" ;;
- ",") character="comma" ;;
- ".") character="dot" ;;
- "/") character="slash" ;;
- "'") character="apostrophe" ;;
- ";") character="semicolon" ;;
- '\') character="backslash" ;;
- '`') character="grave_accent" ;;
- "[") character="bracket_left" ;;
- "]") character="bracket_right" ;;
- "_") character="shift-minus" ;;
- "+") character="shift-equal" ;;
- "?") character="shift-slash" ;;
- "<") character="shift-comma" ;;
- ">") character="shift-dot" ;;
- '"') character="shift-apostrophe" ;;
- ":") character="shift-semicolon" ;;
- "|") character="shift-backslash" ;;
- "~") character="shift-grave_accent" ;;
- "{") character="shift-bracket_left" ;;
- "}") character="shift-bracket_right" ;;
- "A") character="shift-a" ;;
- "B") character="shift-b" ;;
- "C") character="shift-c" ;;
- "D") character="shift-d" ;;
- "E") character="shift-e" ;;
- "F") character="shift-f" ;;
- "G") character="shift-g" ;;
- "H") character="shift-h" ;;
- "I") character="shift-i" ;;
- "J") character="shift-j" ;;
- "K") character="shift-k" ;;
- "L") character="shift-l" ;;
- "M") character="shift-m" ;;
- "N") character="shift-n" ;;
- "O") character="shift-o" ;;
- "P") character="shift-p" ;;
- "Q") character="shift-q" ;;
- "R") character="shift-r" ;;
- "S") character="shift-s" ;;
- "T") character="shift-t" ;;
- "U") character="shift-u" ;;
- "V") character="shift-v" ;;
- "W") character="shift-w" ;;
- "X") character="shift=x" ;;
- "Y") character="shift-y" ;;
- "Z") character="shift-z" ;;
- "!") character="shift-1" ;;
- "@") character="shift-2" ;;
- "#") character="shift-3" ;;
- '$') character="shift-4" ;;
- "%") character="shift-5" ;;
- "^") character="shift-6" ;;
- "&") character="shift-7" ;;
- "*") character="shift-8" ;;
- "(") character="shift-9" ;;
- ")") character="shift-0" ;;
- esac
- qm sendkey $VMID "$character"
- done
- qm sendkey $VMID ret
+ echo -e "${DGN}Sending line: ${YW}$1${CL}"
+ for ((i = 0; i < ${#1}; i++)); do
+ character=${1:i:1}
+ case $character in
+ " ") character="spc" ;;
+ "-") character="minus" ;;
+ "=") character="equal" ;;
+ ",") character="comma" ;;
+ ".") character="dot" ;;
+ "/") character="slash" ;;
+ "'") character="apostrophe" ;;
+ ";") character="semicolon" ;;
+ '\') character="backslash" ;;
+ '`') character="grave_accent" ;;
+ "[") character="bracket_left" ;;
+ "]") character="bracket_right" ;;
+ "_") character="shift-minus" ;;
+ "+") character="shift-equal" ;;
+ "?") character="shift-slash" ;;
+ "<") character="shift-comma" ;;
+ ">") character="shift-dot" ;;
+ '"') character="shift-apostrophe" ;;
+ ":") character="shift-semicolon" ;;
+ "|") character="shift-backslash" ;;
+ "~") character="shift-grave_accent" ;;
+ "{") character="shift-bracket_left" ;;
+ "}") character="shift-bracket_right" ;;
+ "A") character="shift-a" ;;
+ "B") character="shift-b" ;;
+ "C") character="shift-c" ;;
+ "D") character="shift-d" ;;
+ "E") character="shift-e" ;;
+ "F") character="shift-f" ;;
+ "G") character="shift-g" ;;
+ "H") character="shift-h" ;;
+ "I") character="shift-i" ;;
+ "J") character="shift-j" ;;
+ "K") character="shift-k" ;;
+ "L") character="shift-l" ;;
+ "M") character="shift-m" ;;
+ "N") character="shift-n" ;;
+ "O") character="shift-o" ;;
+ "P") character="shift-p" ;;
+ "Q") character="shift-q" ;;
+ "R") character="shift-r" ;;
+ "S") character="shift-s" ;;
+ "T") character="shift-t" ;;
+ "U") character="shift-u" ;;
+ "V") character="shift-v" ;;
+ "W") character="shift-w" ;;
+ "X") character="shift=x" ;;
+ "Y") character="shift-y" ;;
+ "Z") character="shift-z" ;;
+ "!") character="shift-1" ;;
+ "@") character="shift-2" ;;
+ "#") character="shift-3" ;;
+ '$') character="shift-4" ;;
+ "%") character="shift-5" ;;
+ "^") character="shift-6" ;;
+ "&") character="shift-7" ;;
+ "*") character="shift-8" ;;
+ "(") character="shift-9" ;;
+ ")") character="shift-0" ;;
+ esac
+ qm sendkey $VMID "$character"
+ done
+ qm sendkey $VMID ret
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "OPNsense VM" --yesno "This will create a New OPNsense VM. Proceed?" 10 58); then
- :
+ :
else
- header_info && echo -e "⚠ User exited script \n" && exit
+ header_info && echo -e "⚠ User exited script \n" && exit
fi
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}"
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${CROSS} This script will not work with PiMox! \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${CROSS} This script will not work with PiMox! \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "⚠ User exited script \n"
- exit
+ clear
+ echo -e "⚠ User exited script \n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_CACHE=""
- HN="opnsense"
- CPU_TYPE=""
- CORE_COUNT="4"
- RAM_SIZE="8192"
- BRG="vmbr0"
- IP_ADDR=""
- WAN_IP_ADDR=""
- LAN_GW=""
- WAN_GW=""
- NETMASK=""
- WAN_NETMASK=""
- VLAN=""
- MAC=$GEN_MAC
- WAN_MAC=$GEN_MAC_LAN
- WAN_BRG="vmbr1"
- MTU=""
- START_VM="yes"
- METHOD="default"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_CACHE=""
+ HN="opnsense"
+ CPU_TYPE=""
+ CORE_COUNT="4"
+ RAM_SIZE="8192"
+ BRG="vmbr0"
+ IP_ADDR=""
+ WAN_IP_ADDR=""
+ LAN_GW=""
+ WAN_GW=""
+ NETMASK=""
+ WAN_NETMASK=""
+ VLAN=""
+ MAC=$GEN_MAC
+ WAN_MAC=$GEN_MAC_LAN
+ WAN_BRG="vmbr1"
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
- echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
- echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
- if ! grep -q "^iface ${BRG}" /etc/network/interfaces; then
- msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces"
- exit
- else
- echo -e "${DGN}Using LAN Bridge: ${BGN}${BRG}${CL}"
- fi
- echo -e "${DGN}Using LAN VLAN: ${BGN}Default${CL}"
- echo -e "${DGN}Using LAN MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${DGN}Using WAN MAC Address: ${BGN}${WAN_MAC}${CL}"
- if ! grep -q "^iface ${WAN_BRG}" /etc/network/interfaces; then
- msg_error "Bridge '${WAN_BRG}' does not exist in /etc/network/interfaces"
- exit
- else
- echo -e "${DGN}Using WAN Bridge: ${BGN}${WAN_BRG}${CL}"
- fi
- echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${BL}Creating a OPNsense VM using the above default settings${CL}"
+ echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
+ echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
+ if ! grep -q "^iface ${BRG}" /etc/network/interfaces; then
+ msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces"
+ exit
+ else
+ echo -e "${DGN}Using LAN Bridge: ${BGN}${BRG}${CL}"
+ fi
+ echo -e "${DGN}Using LAN VLAN: ${BGN}Default${CL}"
+ echo -e "${DGN}Using LAN MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${DGN}Using WAN MAC Address: ${BGN}${WAN_MAC}${CL}"
+ if ! grep -q "^iface ${WAN_BRG}" /etc/network/interfaces; then
+ msg_error "Bridge '${WAN_BRG}' does not exist in /etc/network/interfaces"
+ exit
+ else
+ echo -e "${DGN}Using WAN Bridge: ${BGN}${WAN_BRG}${CL}"
+ fi
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${BL}Creating a OPNsense VM using the above default settings${CL}"
}
function advanced_settings() {
- local ip_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$'
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
- else
- exit-script
- fi
- done
-
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
- else
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
- fi
- else
- exit-script
- fi
-
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
- else
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
- fi
- else
- exit-script
- fi
-
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
- else
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
- fi
- else
- exit-script
- fi
-
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 OPNsense --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="OPNsense"
- else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- fi
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
- else
- exit-script
- fi
-
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 4 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- fi
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
- else
- exit-script
- fi
-
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 8192 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="8192"
- fi
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
- else
- exit-script
- fi
-
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- fi
- if ! grep -q "^iface ${BRG}" /etc/network/interfaces; then
- msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces"
- exit
- fi
- echo -e "${DGN}Using LAN Bridge: ${BGN}$BRG${CL}"
- else
- exit-script
- fi
-
- if IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN IP" 8 58 $IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $IP_ADDR ]; then
- echo -e "${DGN}Using DHCP AS LAN IP ADDRESS${CL}"
- else
- if [[ -n "$IP_ADDR" && ! "$IP_ADDR" =~ $ip_regex ]]; then
- msg_error "Invalid IP Address format for LAN IP. Needs to be 0.0.0.0, was $IP_ADDR"
- exit
- fi
- echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$IP_ADDR${CL}"
- if LAN_GW=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN GATEWAY IP" 8 58 $LAN_GW --title "LAN GATEWAY IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $LAN_GW ]; then
- echo -e "${DGN}Gateway needs to be set if ip is not dhcp${CL}"
- exit-script
+ local ip_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$'
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
fi
- if [[ -n "$LAN_GW" && ! "$LAN_GW" =~ $ip_regex ]]; then
- msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was $LAN_GW"
- exit
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
fi
- echo -e "${DGN}Using LAN GATEWAY ADDRESS: ${BGN}$LAN_GW${CL}"
- fi
- if NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN netmmask (24 for example)" 8 58 $NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $NETMASK ]; then
- echo -e "${DGN}Netmask needs to be set if ip is not dhcp${CL}"
- fi
- if [[ -n "$NETMASK" && ! ("$NETMASK" =~ ^[0-9]+$ && "$NETMASK" -ge 1 && "$NETMASK" -le 32) ]]; then
- msg_error "Invalid LAN NETMASK format. Needs to be 1-32, was $NETMASK"
- exit
- fi
- echo -e "${DGN}Using LAN NETMASK: ${BGN}$NETMASK${CL}"
- else
+ else
exit-script
- fi
fi
- else
- exit-script
- fi
- if WAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr1 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $WAN_BRG ]; then
- WAN_BRG="vmbr1"
- fi
- if ! grep -q "^iface ${WAN_BRG}" /etc/network/interfaces; then
- msg_error "WAN Bridge '${WAN_BRG}' does not exist in /etc/network/interfaces"
- exit
- fi
- echo -e "${DGN}Using WAN Bridge: ${BGN}$WAN_BRG${CL}"
- else
- exit-script
- fi
-
- if WAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN IP" 8 58 $WAN_IP_ADDR --title "WAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $WAN_IP_ADDR ]; then
- echo -e "${DGN}Using DHCP AS WAN IP ADDRESS${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- if [[ -n "$WAN_IP_ADDR" && ! "$WAN_IP_ADDR" =~ $ip_regex ]]; then
- msg_error "Invalid IP Address format for WAN IP. Needs to be 0.0.0.0, was $WAN_IP_ADDR"
- exit
- fi
- echo -e "${DGN}Using WAN IP ADDRESS: ${BGN}$WAN_IP_ADDR${CL}"
- if WAN_GW=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN GATEWAY IP" 8 58 $WAN_GW --title "WAN GATEWAY IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $WAN_GW ]; then
- echo -e "${DGN}Gateway needs to be set if ip is not dhcp${CL}"
- exit-script
- fi
- if [[ -n "$WAN_GW" && ! "$WAN_GW" =~ $ip_regex ]]; then
- msg_error "Invalid IP Address format for WAN Gateway. Needs to be 0.0.0.0, was $WAN_GW"
- exit
- fi
- echo -e "${DGN}Using WAN GATEWAY ADDRESS: ${BGN}$WAN_GW${CL}"
- else
exit-script
- fi
- if WAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN netmmask (24 for example)" 8 58 $WAN_NETMASK --title "WAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $WAN_NETMASK ]; then
- echo -e "${DGN}WAN Netmask needs to be set if ip is not dhcp${CL}"
+ fi
+
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
fi
- if [[ -n "$WAN_NETMASK" && ! ("$WAN_NETMASK" =~ ^[0-9]+$ && "$WAN_NETMASK" -ge 1 && "$WAN_NETMASK" -le 32) ]]; then
- msg_error "Invalid WAN NETMASK format. Needs to be 1-32, was $WAN_NETMASK"
- exit
- fi
- echo -e "${DGN}Using WAN NETMASK: ${BGN}$WAN_NETMASK${CL}"
- else
+ else
exit-script
- fi
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- else
- MAC="$MAC1"
- fi
- echo -e "${DGN}Using LAN MAC Address: ${BGN}$MAC${CL}"
- else
- exit-script
- fi
- if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC2 ]; then
- WAN_MAC="$GEN_MAC_LAN"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 OPNsense --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="OPNsense"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ fi
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
else
- WAN_MAC="$MAC2"
+ exit-script
fi
- echo -e "${DGN}Using WAN MAC Address: ${BGN}$WAN_MAC${CL}"
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OPNsense VM?" --no-button Do-Over 10 58); then
- echo -e "${RD}Creating a OPNsense VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 4 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ fi
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ exit-script
+ fi
+
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 8192 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="8192"
+ fi
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ else
+ exit-script
+ fi
+
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN Bridge" 8 58 vmbr0 --title "LAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ fi
+ if ! grep -q "^iface ${BRG}" /etc/network/interfaces; then
+ msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces"
+ exit
+ fi
+ echo -e "${DGN}Using LAN Bridge: ${BGN}$BRG${CL}"
+ else
+ exit-script
+ fi
+
+ if IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN IP" 8 58 $IP_ADDR --title "LAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $IP_ADDR ]; then
+ echo -e "${DGN}Using DHCP AS LAN IP ADDRESS${CL}"
+ else
+ if [[ -n "$IP_ADDR" && ! "$IP_ADDR" =~ $ip_regex ]]; then
+ msg_error "Invalid IP Address format for LAN IP. Needs to be 0.0.0.0, was $IP_ADDR"
+ exit
+ fi
+ echo -e "${DGN}Using LAN IP ADDRESS: ${BGN}$IP_ADDR${CL}"
+ if LAN_GW=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN GATEWAY IP" 8 58 $LAN_GW --title "LAN GATEWAY IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $LAN_GW ]; then
+ echo -e "${DGN}Gateway needs to be set if ip is not dhcp${CL}"
+ exit-script
+ fi
+ if [[ -n "$LAN_GW" && ! "$LAN_GW" =~ $ip_regex ]]; then
+ msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was $LAN_GW"
+ exit
+ fi
+ echo -e "${DGN}Using LAN GATEWAY ADDRESS: ${BGN}$LAN_GW${CL}"
+ fi
+ if NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN netmmask (24 for example)" 8 58 $NETMASK --title "LAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $NETMASK ]; then
+ echo -e "${DGN}Netmask needs to be set if ip is not dhcp${CL}"
+ fi
+ if [[ -n "$NETMASK" && ! ("$NETMASK" =~ ^[0-9]+$ && "$NETMASK" -ge 1 && "$NETMASK" -le 32) ]]; then
+ msg_error "Invalid LAN NETMASK format. Needs to be 1-32, was $NETMASK"
+ exit
+ fi
+ echo -e "${DGN}Using LAN NETMASK: ${BGN}$NETMASK${CL}"
+ else
+ exit-script
+ fi
+ fi
+ else
+ exit-script
+ fi
+
+ if WAN_BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN Bridge" 8 58 vmbr1 --title "WAN BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $WAN_BRG ]; then
+ WAN_BRG="vmbr1"
+ fi
+ if ! grep -q "^iface ${WAN_BRG}" /etc/network/interfaces; then
+ msg_error "WAN Bridge '${WAN_BRG}' does not exist in /etc/network/interfaces"
+ exit
+ fi
+ echo -e "${DGN}Using WAN Bridge: ${BGN}$WAN_BRG${CL}"
+ else
+ exit-script
+ fi
+
+ if WAN_IP_ADDR=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN IP" 8 58 $WAN_IP_ADDR --title "WAN IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $WAN_IP_ADDR ]; then
+ echo -e "${DGN}Using DHCP AS WAN IP ADDRESS${CL}"
+ else
+ if [[ -n "$WAN_IP_ADDR" && ! "$WAN_IP_ADDR" =~ $ip_regex ]]; then
+ msg_error "Invalid IP Address format for WAN IP. Needs to be 0.0.0.0, was $WAN_IP_ADDR"
+ exit
+ fi
+ echo -e "${DGN}Using WAN IP ADDRESS: ${BGN}$WAN_IP_ADDR${CL}"
+ if WAN_GW=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN GATEWAY IP" 8 58 $WAN_GW --title "WAN GATEWAY IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $WAN_GW ]; then
+ echo -e "${DGN}Gateway needs to be set if ip is not dhcp${CL}"
+ exit-script
+ fi
+ if [[ -n "$WAN_GW" && ! "$WAN_GW" =~ $ip_regex ]]; then
+ msg_error "Invalid IP Address format for WAN Gateway. Needs to be 0.0.0.0, was $WAN_GW"
+ exit
+ fi
+ echo -e "${DGN}Using WAN GATEWAY ADDRESS: ${BGN}$WAN_GW${CL}"
+ else
+ exit-script
+ fi
+ if WAN_NETMASK=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN netmmask (24 for example)" 8 58 $WAN_NETMASK --title "WAN NETMASK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $WAN_NETMASK ]; then
+ echo -e "${DGN}WAN Netmask needs to be set if ip is not dhcp${CL}"
+ fi
+ if [[ -n "$WAN_NETMASK" && ! ("$WAN_NETMASK" =~ ^[0-9]+$ && "$WAN_NETMASK" -ge 1 && "$WAN_NETMASK" -le 32) ]]; then
+ msg_error "Invalid WAN NETMASK format. Needs to be 1-32, was $WAN_NETMASK"
+ exit
+ fi
+ echo -e "${DGN}Using WAN NETMASK: ${BGN}$WAN_NETMASK${CL}"
+ else
+ exit-script
+ fi
+ fi
+ else
+ exit-script
+ fi
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a WAN MAC Address" 8 58 $GEN_MAC --title "WAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ else
+ MAC="$MAC1"
+ fi
+ echo -e "${DGN}Using LAN MAC Address: ${BGN}$MAC${CL}"
+ else
+ exit-script
+ fi
+
+ if MAC2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a LAN MAC Address" 8 58 $GEN_MAC_LAN --title "LAN MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC2 ]; then
+ WAN_MAC="$GEN_MAC_LAN"
+ else
+ WAN_MAC="$MAC2"
+ fi
+ echo -e "${DGN}Using WAN MAC Address: ${BGN}$WAN_MAC${CL}"
+ else
+ exit-script
+ fi
+
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create OPNsense VM?" --no-button Do-Over 10 58); then
+ echo -e "${RD}Creating a OPNsense VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
arch_check
@@ -515,29 +515,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -554,39 +554,39 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a OPNsense VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags proxmox-helper-scripts -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags proxmox-helper-scripts -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=2G \
- -boot order=scsi0 \
- -serial0 socket \
- -tags community-script >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=2G \
+ -boot order=scsi0 \
+ -serial0 socket \
+ -tags community-script >/dev/null
qm resize $VMID scsi0 10G >/dev/null
DESCRIPTION=$(
- cat <
@@ -599,7 +599,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -619,7 +619,7 @@ qm set "$VMID" -description "$DESCRIPTION" >/dev/null
msg_info "Bridge interfaces are being added."
qm set $VMID \
- -net0 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} 2>/dev/null
+ -net0 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} 2>/dev/null
msg_ok "Bridge interfaces have been successfully added."
msg_ok "Created a OPNsense VM ${CL}${BL}(${HN})"
@@ -629,7 +629,7 @@ sleep 90
send_line_to_vm "root"
send_line_to_vm "fetch https://raw.githubusercontent.com/opnsense/update/master/src/bootstrap/opnsense-bootstrap.sh.in"
qm set $VMID \
- -net1 virtio,bridge=${WAN_BRG},macaddr=${WAN_MAC} &>/dev/null
+ -net1 virtio,bridge=${WAN_BRG},macaddr=${WAN_MAC} &>/dev/null
sleep 10
send_line_to_vm "sh ./opnsense-bootstrap.sh.in -y -f -r 25.1"
msg_ok "OPNsense VM is being installed, do not close the terminal, or the installation will fail."
@@ -640,47 +640,47 @@ send_line_to_vm "opnsense"
send_line_to_vm "2"
if [ "$IP_ADDR" != "" ]; then
- send_line_to_vm "1"
- send_line_to_vm "n"
- send_line_to_vm "${IP_ADDR}"
- send_line_to_vm "${NETMASK}"
- send_line_to_vm "${LAN_GW}"
- send_line_to_vm "n"
- send_line_to_vm " "
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm " "
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm "n"
+ send_line_to_vm "1"
+ send_line_to_vm "n"
+ send_line_to_vm "${IP_ADDR}"
+ send_line_to_vm "${NETMASK}"
+ send_line_to_vm "${LAN_GW}"
+ send_line_to_vm "n"
+ send_line_to_vm " "
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm " "
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
else
- send_line_to_vm "1"
- send_line_to_vm "y"
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm " "
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm "n"
+ send_line_to_vm "1"
+ send_line_to_vm "y"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm " "
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
fi
#we need to wait for the Config changes to be saved
sleep 20
if [ "$WAN_IP_ADDR" != "" ]; then
- send_line_to_vm "2"
- send_line_to_vm "2"
- send_line_to_vm "n"
- send_line_to_vm "${WAN_IP_ADDR}"
- send_line_to_vm "${NETMASK}"
- send_line_to_vm "${LAN_GW}"
- send_line_to_vm "n"
- send_line_to_vm " "
- send_line_to_vm "n"
- send_line_to_vm " "
- send_line_to_vm "n"
- send_line_to_vm "n"
- send_line_to_vm "n"
+ send_line_to_vm "2"
+ send_line_to_vm "2"
+ send_line_to_vm "n"
+ send_line_to_vm "${WAN_IP_ADDR}"
+ send_line_to_vm "${NETMASK}"
+ send_line_to_vm "${LAN_GW}"
+ send_line_to_vm "n"
+ send_line_to_vm " "
+ send_line_to_vm "n"
+ send_line_to_vm " "
+ send_line_to_vm "n"
+ send_line_to_vm "n"
+ send_line_to_vm "n"
fi
sleep 10
send_line_to_vm "0"
@@ -688,9 +688,9 @@ msg_ok "Started OPNsense VM"
msg_ok "Completed Successfully!\n"
if [ "$IP_ADDR" != "" ]; then
- echo -e "${INFO}${YW} Access it using the following URL:${CL}"
- echo -e "${TAB}${GATEWAY}${BGN}http://${IP_ADDR}${CL}"
+ echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+ echo -e "${TAB}${GATEWAY}${BGN}http://${IP_ADDR}${CL}"
else
- echo -e "${INFO}${YW} LAN IP was DHCP.${CL}"
- echo -e "${INFO}${BGN}To find the IP login to the VM shell${CL}"
+ echo -e "${INFO}${YW} LAN IP was DHCP.${CL}"
+ echo -e "${INFO}${BGN}To find the IP login to the VM shell${CL}"
fi
diff --git a/vm/owncloud-vm.sh b/vm/owncloud-vm.sh
index 5b6c186ef..7db765ad3 100644
--- a/vm/owncloud-vm.sh
+++ b/vm/owncloud-vm.sh
@@ -8,8 +8,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
______ __ __ _______ __ _ ____ ___
/_ __/_ _________ / //_/__ __ __ ___ _ _____ / ___/ /__ __ _____/ / | | / / |/ /
/ / / // / __/ _ \/ ,< / -_) // / / _ \ |/|/ / _ \/ /__/ / _ \/ // / _ / | |/ / /|_/ /
@@ -47,322 +47,322 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$NAME" --yesno "This will create a New $NAME. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "⚠ User exited script \n" && exit
+ header_info && echo -e "⚠ User exited script \n" && exit
fi
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- msg_error "This script will not work with PiMox! \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ msg_error "This script will not work with PiMox! \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "⚠ User exited script \n"
- exit
+ clear
+ echo -e "⚠ User exited script \n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_CACHE=""
- HN="turnkey-owncloud-vm"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="no"
- METHOD="default"
- echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
- echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
- echo -e "${BL}Creating a $NAME using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_CACHE=""
+ HN="turnkey-owncloud-vm"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="no"
+ METHOD="default"
+ echo -e "${DGN}Using Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${DGN}Using Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ echo -e "${DGN}Using Hostname: ${BGN}${HN}${CL}"
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${DGN}Allocated Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${DGN}Allocated RAM: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${DGN}Using Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${DGN}Using MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${DGN}Using VLAN: ${BGN}Default${CL}"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
+ echo -e "${BL}Creating a $NAME using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DGN}Using Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DGN}Using Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-owncloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="turnkey-owncloud-vm"
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DGN}Using Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 turnkey-owncloud-vm --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="turnkey-owncloud-vm"
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${DGN}Using Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${DGN}Using CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${DGN}Using CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${DGN}Allocated Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${DGN}Allocated RAM: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${DGN}Using Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${DGN}Using MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${DGN}Using Vlan: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DGN}Using Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
- echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $NAME?" --no-button Do-Over 10 58); then
+ echo -e "${RD}Creating a $NAME using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -375,29 +375,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -413,39 +413,39 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1,2}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a $NAME"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios seabios${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
pvesm alloc $STORAGE $VMID $DISK1 12G 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
- -scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
- -boot order='scsi1;scsi0' >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN} \
+ -scsi1 ${DISK2_REF},${DISK_CACHE}${THIN} \
+ -boot order='scsi1;scsi0' >/dev/null
DESCRIPTION=$(
- cat <
@@ -458,7 +458,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -477,9 +477,9 @@ EOF
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
msg_ok "Created a $NAME ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting $NAME"
- qm start $VMID
- msg_ok "Started $NAME"
+ msg_info "Starting $NAME"
+ qm start $VMID
+ msg_ok "Started $NAME"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/ubuntu2204-vm.sh b/vm/ubuntu2204-vm.sh
index a662efb3c..2946da3e7 100644
--- a/vm/ubuntu2204-vm.sh
+++ b/vm/ubuntu2204-vm.sh
@@ -7,8 +7,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
__ ____ __ ___ ___ ____ __ __ _ ____ ___
/ / / / /_ __ ______ / /___ __ |__ \|__ \ / __ \/ // / | | / / |/ /
/ / / / __ \/ / / / __ \/ __/ / / / __/ /__/ / / / / / // /_ | | / / /|_/ /
@@ -63,340 +63,340 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 22.04 VM" --yesno "This will create a New Ubuntu 22.04 VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_SIZE="5G"
- DISK_CACHE=""
- HN="ubuntu"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_SIZE="5G"
+ DISK_CACHE=""
+ HN="ubuntu"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="ubuntu"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="ubuntu"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 22.04 VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 22.04 VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 22.04 VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -408,29 +408,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -446,38 +446,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir | cifs)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a Ubuntu 22.04 VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
- -ide2 ${STORAGE}:cloudinit \
- -boot order=scsi0 \
- -serial0 socket >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
+ -ide2 ${STORAGE}:cloudinit \
+ -boot order=scsi0 \
+ -serial0 socket >/dev/null
DESCRIPTION=$(
- cat <
@@ -490,7 +490,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -508,18 +508,18 @@ EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
- msg_info "Resizing disk to $DISK_SIZE GB"
- qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
+ msg_info "Resizing disk to $DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
- msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
- qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
+ msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Ubuntu 22.04 VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting Ubuntu 22.04 VM"
- qm start $VMID
- msg_ok "Started Ubuntu 22.04 VM"
+ msg_info "Starting Ubuntu 22.04 VM"
+ qm start $VMID
+ msg_ok "Started Ubuntu 22.04 VM"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/ubuntu2404-vm.sh b/vm/ubuntu2404-vm.sh
index 28f1f4e20..04afdc82a 100644
--- a/vm/ubuntu2404-vm.sh
+++ b/vm/ubuntu2404-vm.sh
@@ -8,8 +8,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
__ ____ __ ___ __ __ ____ __ __ _ ____ ___
/ / / / /_ __ ______ / /___ __ |__ \/ // / / __ \/ // / | | / / |/ /
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / // /_ | | / / /|_/ /
@@ -66,340 +66,340 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Ubuntu 24.04 VM" --yesno "This will create a New Ubuntu 24.04 VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_SIZE="7G"
- DISK_CACHE=""
- HN="ubuntu"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_SIZE="7G"
+ DISK_CACHE=""
+ HN="ubuntu"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="ubuntu"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="ubuntu"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 24.04 VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Ubuntu 24.04 VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Ubuntu 24.04 VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
arch_check
@@ -410,29 +410,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -448,38 +448,38 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir | cifs)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a Ubuntu 24.04 VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
- -ide2 ${STORAGE}:cloudinit \
- -boot order=scsi0 \
- -serial0 socket >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
+ -ide2 ${STORAGE}:cloudinit \
+ -boot order=scsi0 \
+ -serial0 socket >/dev/null
DESCRIPTION=$(
- cat <
@@ -492,7 +492,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -510,18 +510,18 @@ EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
- msg_info "Resizing disk to $DISK_SIZE GB"
- qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
+ msg_info "Resizing disk to $DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
- msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
- qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
+ msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Ubuntu 24.04 VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting Ubuntu 24.04 VM"
- qm start $VMID
- msg_ok "Started Ubuntu 24.04 VM"
+ msg_info "Starting Ubuntu 24.04 VM"
+ qm start $VMID
+ msg_ok "Started Ubuntu 24.04 VM"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/ubuntu2410-vm.sh b/vm/ubuntu2410-vm.sh
index 82d8519c3..071062fc4 100644
--- a/vm/ubuntu2410-vm.sh
+++ b/vm/ubuntu2410-vm.sh
@@ -7,8 +7,8 @@
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
__ ____ __ ___ __ __ _______ _ ____ ___
/ / / / /_ __ ______ / /___ __ |__ \/ // / < / __ \ | | / / |/ /
/ / / / __ \/ / / / __ \/ __/ / / / __/ / // /_ / / / / / | | / / /|_/ /
@@ -66,467 +66,467 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "$command"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "$command"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "$APP" --yesno "This will create a New $APP. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function init_settings() {
- VMID="$(get_valid_nextid)"
- HN="ubuntu"
- DISK_SIZE="8G"
- DISK_CACHE=""
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="2048"
- MACHINE_TYPE="i440fx"
- MACHINE=""
- FORMAT=",efitype=4m"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
+ VMID="$(get_valid_nextid)"
+ HN="ubuntu"
+ DISK_SIZE="8G"
+ DISK_CACHE=""
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="2048"
+ MACHINE_TYPE="i440fx"
+ MACHINE=""
+ FORMAT=",efitype=4m"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
}
function default_settings() {
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using default settings${CL}"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using default settings${CL}"
}
function apply_env_overrides() {
- METHOD="env"
- [ -n "$var_vmid" ] && VMID="$var_vmid"
- HN=$(echo "${var_hostname,,}" | tr -cd '[:alnum:]-')
- [[ -z "$HN" ]] && HN="ubuntu"
- [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]] && {
- msg_error "Invalid hostname: $HN"
- exit 1
- }
+ METHOD="env"
+ [ -n "$var_vmid" ] && VMID="$var_vmid"
+ HN=$(echo "${var_hostname,,}" | tr -cd '[:alnum:]-')
+ [[ -z "$HN" ]] && HN="ubuntu"
+ [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]] && {
+ msg_error "Invalid hostname: $HN"
+ exit 1
+ }
- case "$var_machine" in
- q35)
- MACHINE_TYPE="q35"
- FORMAT=""
- MACHINE=" -machine q35"
- ;;
- *)
- MACHINE_TYPE="i440fx"
- FORMAT=",efitype=4m"
- MACHINE=""
- ;;
- esac
+ case "$var_machine" in
+ q35)
+ MACHINE_TYPE="q35"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ ;;
+ *)
+ MACHINE_TYPE="i440fx"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ ;;
+ esac
- case "$var_cpu_type" in
- 1) CPU_TYPE=" -cpu host" ;;
- *) CPU_TYPE="" ;;
- esac
+ case "$var_cpu_type" in
+ 1) CPU_TYPE=" -cpu host" ;;
+ *) CPU_TYPE="" ;;
+ esac
- case "$var_disk_cache" in
- 1) DISK_CACHE="cache=writethrough," ;;
- *) DISK_CACHE="" ;;
- esac
+ case "$var_disk_cache" in
+ 1) DISK_CACHE="cache=writethrough," ;;
+ *) DISK_CACHE="" ;;
+ esac
- [[ "$var_cpu" =~ ^[1-9][0-9]*$ ]] && CORE_COUNT="$var_cpu" || CORE_COUNT="2"
- [[ "$var_ram" =~ ^[1-9][0-9]*$ ]] && RAM_SIZE="$var_ram" || RAM_SIZE="2048"
- [[ -n "$var_disk" ]] && DISK_SIZE="$var_disk" || DISK_SIZE="8G"
- [ -n "$var_bridge" ] && BRG="$var_bridge"
- [ -z "$BRG" ] && BRG="vmbr0"
+ [[ "$var_cpu" =~ ^[1-9][0-9]*$ ]] && CORE_COUNT="$var_cpu" || CORE_COUNT="2"
+ [[ "$var_ram" =~ ^[1-9][0-9]*$ ]] && RAM_SIZE="$var_ram" || RAM_SIZE="2048"
+ [[ -n "$var_disk" ]] && DISK_SIZE="$var_disk" || DISK_SIZE="8G"
+ [ -n "$var_bridge" ] && BRG="$var_bridge"
+ [ -z "$BRG" ] && BRG="vmbr0"
- [ -n "$var_mac" ] && MAC="$var_mac"
- [ -z "$MAC" ] && MAC="$GEN_MAC"
- VLAN=${var_vlan:+",tag=$var_vlan"}
- MTU=${var_mtu:+",mtu=$var_mtu"}
- START_VM="$var_start_vm"
+ [ -n "$var_mac" ] && MAC="$var_mac"
+ [ -z "$MAC" ] && MAC="$GEN_MAC"
+ VLAN=${var_vlan:+",tag=$var_vlan"}
+ MTU=${var_mtu:+",mtu=$var_mtu"}
+ START_VM="$var_start_vm"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}${CPU_TYPE:+Host}${CPU_TYPE:-KVM64}${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using environment settings${CL}"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE_TYPE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}${DISK_CACHE:-None}${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}${CPU_TYPE:+Host}${CPU_TYPE:-KVM64}${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}${var_vlan:-Default}${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}${var_mtu:-Default}${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}${START_VM}${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using environment settings${CL}"
}
function validate_env_settings() {
- [[ -n "$var_hostname" ]] && {
- HN_CLEANED=$(echo "$var_hostname" | tr -cd '[:alnum:]-')
- if [[ ! "$HN_CLEANED" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
- msg_error "Invalid hostname: $var_hostname"
- exit 1
- fi
- }
+ [[ -n "$var_hostname" ]] && {
+ HN_CLEANED=$(echo "$var_hostname" | tr -cd '[:alnum:]-')
+ if [[ ! "$HN_CLEANED" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
+ msg_error "Invalid hostname: $var_hostname"
+ exit 1
+ fi
+ }
- [[ -n "$var_vmid" && ! "$var_vmid" =~ ^[1-9][0-9]{2,}$ ]] && {
- msg_error "Invalid VMID: must be a number >= 100"
- exit 1
- }
+ [[ -n "$var_vmid" && ! "$var_vmid" =~ ^[1-9][0-9]{2,}$ ]] && {
+ msg_error "Invalid VMID: must be a number >= 100"
+ exit 1
+ }
- [[ -n "$var_cpu" && ! "$var_cpu" =~ ^[1-9][0-9]*$ ]] && {
- msg_error "Invalid CPU core count: must be > 0"
- exit 1
- }
+ [[ -n "$var_cpu" && ! "$var_cpu" =~ ^[1-9][0-9]*$ ]] && {
+ msg_error "Invalid CPU core count: must be > 0"
+ exit 1
+ }
- [[ -n "$var_ram" && ! "$var_ram" =~ ^[1-9][0-9]*$ ]] && {
- msg_error "Invalid RAM size: must be > 0"
- exit 1
- }
+ [[ -n "$var_ram" && ! "$var_ram" =~ ^[1-9][0-9]*$ ]] && {
+ msg_error "Invalid RAM size: must be > 0"
+ exit 1
+ }
- [[ -n "$var_disk" && ! "$var_disk" =~ ^[1-9][0-9]*G$ ]] && {
- msg_error "Invalid disk size: must be like 10G"
- exit 1
- }
+ [[ -n "$var_disk" && ! "$var_disk" =~ ^[1-9][0-9]*G$ ]] && {
+ msg_error "Invalid disk size: must be like 10G"
+ exit 1
+ }
- [[ -n "$var_mac" && ! "$var_mac" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]] && {
- msg_error "Invalid MAC address: $var_mac"
- exit 1
- }
+ [[ -n "$var_mac" && ! "$var_mac" =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]] && {
+ msg_error "Invalid MAC address: $var_mac"
+ exit 1
+ }
- [[ -n "$var_mtu" && ! "$var_mtu" =~ ^[1-9][0-9]{2,4}$ ]] && {
- msg_error "Invalid MTU value: $var_mtu"
- exit 1
- }
+ [[ -n "$var_mtu" && ! "$var_mtu" =~ ^[1-9][0-9]{2,4}$ ]] && {
+ msg_error "Invalid MTU value: $var_mtu"
+ exit 1
+ }
- [[ -n "$var_vlan" && ! "$var_vlan" =~ ^[0-9]{1,4}$ ]] && {
- msg_error "Invalid VLAN tag: must be numeric"
- exit 1
- }
+ [[ -n "$var_vlan" && ! "$var_vlan" =~ ^[0-9]{1,4}$ ]] && {
+ msg_error "Invalid VLAN tag: must be numeric"
+ exit 1
+ }
- [[ -n "$var_start_vm" && ! "$var_start_vm" =~ ^(yes|no)$ ]] && {
- msg_error "var_start_vm must be 'yes' or 'no'"
- exit 1
- }
+ [[ -n "$var_start_vm" && ! "$var_start_vm" =~ ^(yes|no)$ ]] && {
+ msg_error "var_start_vm must be 'yes' or 'no'"
+ exit 1
+ }
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VM_NAME" ]; then
+ HN="ubuntu"
+ else
+ HN=$(echo "${VM_NAME,,}" | tr -cd '[:alnum:]-')
+ fi
+ if [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
+ msg_error "Invalid hostname: $HN. Must be 1–63 chars, alphanumeric or hyphen, and not start/end with hyphen."
+ exit-script
+ fi
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 ubuntu --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VM_NAME" ]; then
- HN="ubuntu"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ "$CPU_TYPE1" = "1" ]; then
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo "${VM_NAME,,}" | tr -cd '[:alnum:]-')
+ exit-script
fi
- if [[ ! "$HN" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
- msg_error "Invalid hostname: $HN. Must be 1–63 chars, alphanumeric or hyphen, and not start/end with hyphen."
- exit-script
- fi
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ "$CPU_TYPE1" = "1" ]; then
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ CORE_COUNT=$(echo "$CORE_COUNT" | tr -cd '[:digit:]')
+ if [[ ! "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
+ msg_error "CPU core count must be a positive integer."
+ exit-script
+ fi
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
else
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit-script
fi
- else
- exit-script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- CORE_COUNT=$(echo "$CORE_COUNT" | tr -cd '[:digit:]')
- if [[ ! "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
- msg_error "CPU core count must be a positive integer."
- exit-script
- fi
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
- else
- exit-script
- fi
-
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- RAM_SIZE=$(echo "$RAM_SIZE" | tr -cd '[:digit:]')
- if [[ ! "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
- msg_error "RAM size must be a positive integer (in MiB)."
- exit-script
- fi
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
- else
- exit-script
- fi
-
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ RAM_SIZE=$(echo "$RAM_SIZE" | tr -cd '[:digit:]')
+ if [[ ! "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
+ msg_error "RAM size must be a positive integer (in MiB)."
+ exit-script
+ fi
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
+ else
+ exit-script
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $APP?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
+ else
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
+ fi
+
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a $APP?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a $APP using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function has_env_overrides() {
- env | grep -qE "^var_(bridge|cpu|cpu_type|disk|disk_cache|hostname|mac|machine|mtu|ram|start_vm|vlan|vmid)="
+ env | grep -qE "^var_(bridge|cpu|cpu_type|disk|disk_cache|hostname|mac|machine|mtu|ram|start_vm|vlan|vmid)="
}
function start_script() {
- header_info
- init_settings
- if has_env_overrides; then
- echo -e "${ADVANCED}${BOLD}${BL}Using Environment Variable Overrides${CL}"
- METHOD="env"
- apply_env_overrides
- elif (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ header_info
+ init_settings
+ if has_env_overrides; then
+ echo -e "${ADVANCED}${BOLD}${BL}Using Environment Variable Overrides${CL}"
+ METHOD="env"
+ apply_env_overrides
+ elif (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
@@ -538,29 +538,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -576,42 +576,42 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir | cifs)
- DISK_EXT=".qcow2"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format qcow2"
- THIN=""
- ;;
+ DISK_EXT=".qcow2"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format qcow2"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a $APP"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags "community-script;ubuntu" -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ -name $HN -tags "community-script;ubuntu" -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
if [[ "$STORAGE_TYPE" != "lvmthin" ]]; then
- pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
+ pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
fi
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
- -ide2 ${STORAGE}:cloudinit \
- -boot order=scsi0 \
- -serial0 socket \
- -smbios1 type=1 \
- --ciuser "ubuntu" -cipassword "ubuntu" >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
+ -ide2 ${STORAGE}:cloudinit \
+ -boot order=scsi0 \
+ -serial0 socket \
+ -smbios1 type=1 \
+ --ciuser "ubuntu" -cipassword "ubuntu" >/dev/null
DESCRIPTION=$(
- cat <
@@ -642,20 +642,20 @@ EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
- msg_info "Resizing disk to $DISK_SIZE GB"
- qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
- msg_ok "Resized disk to ${CL}${BL}${DISK_SIZE}${CL} GB"
+ msg_info "Resizing disk to $DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
+ msg_ok "Resized disk to ${CL}${BL}${DISK_SIZE}${CL} GB"
else
- msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
- qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
- msg_ok "Resized disk to ${CL}${BL}${DEFAULT_DISK_SIZE}${CL} GB"
+ msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
+ msg_ok "Resized disk to ${CL}${BL}${DEFAULT_DISK_SIZE}${CL} GB"
fi
msg_ok "Created a $APP ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting $APP"
- qm start $VMID
- msg_ok "Started $APP"
+ msg_info "Starting $APP"
+ qm start $VMID
+ msg_ok "Started $APP"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/umbrel-os-vm.sh b/vm/umbrel-os-vm.sh
index 0e238d6ee..bdaca5ca2 100644
--- a/vm/umbrel-os-vm.sh
+++ b/vm/umbrel-os-vm.sh
@@ -57,341 +57,341 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "${command}"
- local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
- echo -e "\n$error_message\n"
- cleanup_vmid
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "${command}"
+ local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
+ echo -e "\n$error_message\n"
+ cleanup_vmid
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- post_update_to_api "done" "none"
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ post_update_to_api "done" "none"
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Umbrel OS VM" --yesno "This will create a New Umbrel OS VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
function pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-4](\.[0-9]+)*"; then
- msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
- echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if ! pveversion | grep -Eq "pve-manager/(8\.[1-4]|9\.[0-1])(\.[0-9]+)*"; then
+ msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
+ echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit_script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function default_settings() {
- VMID=$(get_valid_nextid)
- FORMAT=",efitype=4m"
- MACHINE=""
- DISK_CACHE=""
- DISK_SIZE="32G"
- HN="umbrel-os"
- CPU_TYPE=""
- CORE_COUNT="2"
- RAM_SIZE="4096"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above default settings${CL}"
+ VMID=$(get_valid_nextid)
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ DISK_CACHE=""
+ DISK_SIZE="32G"
+ HN="umbrel-os"
+ CPU_TYPE=""
+ CORE_COUNT="2"
+ RAM_SIZE="4096"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ METHOD="advanced"
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
+ "i440fx" "Machine i440fx" ON \
+ "q35" "Machine q35" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $MACH = q35 ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit_script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
- "i440fx" "Machine i440fx" ON \
- "q35" "Machine q35" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $MACH = q35 ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit_script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit_script
fi
- else
- exit_script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit_script
+ exit_script
fi
- else
- exit_script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 umbrel-os --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="umbrel-os"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit_script
fi
- else
- exit_script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 umbrel-os --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="umbrel-os"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "KVM64 (Default)" ON \
+ "1" "Host" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $CPU_TYPE1 = "1" ]; then
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ else
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ fi
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "KVM64 (Default)" ON \
- "1" "Host" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $CPU_TYPE1 = "1" ]; then
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
+ exit_script
fi
- else
- exit_script
- fi
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit_script
fi
- else
- exit_script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
fi
- else
- exit_script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
-
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Umbrel OS VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Umbrel OS VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Umbrel OS VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
arch_check
@@ -402,29 +402,29 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -437,7 +437,7 @@ curl -f#SL -o "$FILE" "$URL"
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
if ! command -v pv &>/dev/null; then
- apt-get update &>/dev/null && apt-get install -y pv &>/dev/null
+ apt-get update &>/dev/null && apt-get install -y pv &>/dev/null
fi
msg_info "Decompressing $FILE with progress${CL}\n"
@@ -449,39 +449,39 @@ msg_ok "Decompressed to ${CL}${BL}${FILE%.xz}${CL}"
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ THIN=""
+ ;;
btrfs)
- DISK_EXT=".raw"
- DISK_REF="$VMID/"
- DISK_IMPORT="-format raw"
- FORMAT=",efitype=4m"
- THIN=""
- ;;
+ DISK_EXT=".raw"
+ DISK_REF="$VMID/"
+ DISK_IMPORT="-format raw"
+ FORMAT=",efitype=4m"
+ THIN=""
+ ;;
esac
for i in {0,1,2}; do
- disk="DISK$i"
- eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
- eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
+ disk="DISK$i"
+ eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
+ eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a Umbrel OS VM"
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
- -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
+ -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
pvesm alloc $STORAGE $VMID $DISK0 4M >/dev/null
qm importdisk $VMID ${FILE_IMG} $STORAGE ${DISK_IMPORT:-} >/dev/null
qm set $VMID \
- -efidisk0 ${DISK0_REF}${FORMAT} \
- -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
- -boot order=scsi0 \
- -serial0 socket >/dev/null
+ -efidisk0 ${DISK0_REF}${FORMAT} \
+ -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
+ -boot order=scsi0 \
+ -serial0 socket >/dev/null
qm set $VMID --agent enabled=1 >/dev/null
DESCRIPTION=$(
- cat <
@@ -513,18 +513,18 @@ EOF
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
- msg_info "Resizing disk to $DISK_SIZE GB"
- qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
+ msg_info "Resizing disk to $DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
- msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
- qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
+ msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
+ qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Umbrel OS VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting Umbrel OS VM"
- qm start $VMID
- msg_ok "Started Umbrel OS VM"
+ msg_info "Starting Umbrel OS VM"
+ qm start $VMID
+ msg_ok "Started Umbrel OS VM"
fi
post_update_to_api "done" "none"
msg_ok "Completed Successfully!\n"
diff --git a/vm/unifi-os-vm.sh b/vm/unifi-os-vm.sh
index cd5b64134..9ac19dbb1 100644
--- a/vm/unifi-os-vm.sh
+++ b/vm/unifi-os-vm.sh
@@ -9,8 +9,8 @@ source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-sc
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/cloud-init.sh) 2>/dev/null || true
function header_info() {
- clear
- cat <<"EOF"
+ clear
+ cat <<"EOF"
__ __ _ _____ ____ _____ _____
/ / / /___ (_) __(_) / __ \/ ___/ / ___/___ ______ _____ _____
/ / / / __ \/ / /_/ / / / / /\__ \ \__ \/ _ \/ ___/ | / / _ \/ ___/
@@ -75,446 +75,446 @@ trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
function error_handler() {
- local exit_code="$?"
- local line_number="$1"
- local command="$2"
- post_update_to_api "failed" "${command}"
- echo -e "\n${RD}[ERROR]${CL} line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing ${YW}$command${CL}\n"
- if qm status $VMID &>/dev/null; then qm stop $VMID &>/dev/null || true; fi
+ local exit_code="$?"
+ local line_number="$1"
+ local command="$2"
+ post_update_to_api "failed" "${command}"
+ echo -e "\n${RD}[ERROR]${CL} line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing ${YW}$command${CL}\n"
+ if qm status $VMID &>/dev/null; then qm stop $VMID &>/dev/null || true; fi
}
function get_valid_nextid() {
- local try_id
- try_id=$(pvesh get /cluster/nextid)
- while true; do
- if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
- try_id=$((try_id + 1))
- continue
- fi
- if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
- try_id=$((try_id + 1))
- continue
- fi
- break
- done
- echo "$try_id"
+ local try_id
+ try_id=$(pvesh get /cluster/nextid)
+ while true; do
+ if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
+ try_id=$((try_id + 1))
+ continue
+ fi
+ break
+ done
+ echo "$try_id"
}
function cleanup_vmid() {
- if qm status $VMID &>/dev/null; then
- qm stop $VMID &>/dev/null
- qm destroy $VMID &>/dev/null
- fi
+ if qm status $VMID &>/dev/null; then
+ qm stop $VMID &>/dev/null
+ qm destroy $VMID &>/dev/null
+ fi
}
function cleanup() {
- popd >/dev/null
- post_update_to_api "done" "none"
- rm -rf $TEMP_DIR
+ popd >/dev/null
+ post_update_to_api "done" "none"
+ rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Unifi OS VM" --yesno "This will create a New Unifi OS VM. Proceed?" 10 58; then
- :
+ :
else
- header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
+ header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
- local msg="$1"
- echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
+ local msg="$1"
+ echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
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}"
}
function check_root() {
- if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
- clear
- msg_error "Please run this script as root."
- echo -e "\nExiting..."
- sleep 2
- exit
- fi
+ if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
+ clear
+ msg_error "Please run this script as root."
+ echo -e "\nExiting..."
+ sleep 2
+ exit
+ fi
}
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
-# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 (NOT 9.1+)
+# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 – 9.1
pve_check() {
- local PVE_VER
- PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
+ local PVE_VER
+ PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
- # Check for Proxmox VE 8.x: allow 8.0–8.9
- if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
- local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR < 0 || MINOR > 9)); then
- msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported: Proxmox VE version 8.0 – 8.9"
- exit 1
+ # Check for Proxmox VE 8.x: allow 8.0–8.9
+ if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
+ local MINOR="${BASH_REMATCH[1]}"
+ if ((MINOR < 0 || MINOR > 9)); then
+ msg_error "This version of Proxmox VE is not supported."
+ msg_error "Supported: Proxmox VE version 8.0 – 8.9"
+ exit 1
+ fi
+ return 0
fi
- return 0
- fi
- # Check for Proxmox VE 9.x: allow ONLY 9.0
- if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
- local MINOR="${BASH_REMATCH[1]}"
- if ((MINOR != 0)); then
- msg_error "This version of Proxmox VE is not yet supported."
- msg_error "Supported: Proxmox VE version 9.0"
- exit 1
+ # Check for Proxmox VE 9.x: allow 9.0–9.1
+ if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
+ local MINOR="${BASH_REMATCH[1]}"
+ if ((MINOR < 0 || MINOR > 1)); then
+ msg_error "This version of Proxmox VE is not yet supported."
+ msg_error "Supported: Proxmox VE version 9.0 – 9.1"
+ exit 1
+ fi
+ return 0
fi
- return 0
- fi
- # All other unsupported versions
- msg_error "This version of Proxmox VE is not supported."
- msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
- exit 1
+ # All other unsupported versions
+ msg_error "This version of Proxmox VE is not supported."
+ msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
+ exit 1
}
function arch_check() {
- if [ "$(dpkg --print-architecture)" != "amd64" ]; then
- echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
- echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
- echo -e "Exiting..."
- sleep 2
- exit
- fi
+ if [ "$(dpkg --print-architecture)" != "amd64" ]; then
+ echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
+ echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
+ echo -e "Exiting..."
+ sleep 2
+ exit
+ fi
}
function ssh_check() {
- if command -v pveversion >/dev/null 2>&1; then
- if [ -n "${SSH_CLIENT:+x}" ]; then
- if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
- echo "you've been warned"
- else
- clear
- exit
- fi
+ if command -v pveversion >/dev/null 2>&1; then
+ if [ -n "${SSH_CLIENT:+x}" ]; then
+ if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
+ echo "you've been warned"
+ else
+ clear
+ exit
+ fi
+ fi
fi
- fi
}
function exit-script() {
- clear
- echo -e "\n${CROSS}${RD}User exited script${CL}\n"
- exit
+ clear
+ echo -e "\n${CROSS}${RD}User exited script${CL}\n"
+ exit
}
function select_os() {
- if OS_CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT OS" --radiolist \
- "Choose Operating System for UniFi OS VM" 12 68 2 \
- "debian13" "Debian 13 (Trixie) - Latest" ON \
- "ubuntu2404" "Ubuntu 24.04 LTS (Noble)" OFF \
- 3>&1 1>&2 2>&3); then
- case $OS_CHOICE in
- debian13)
- OS_TYPE="debian"
- OS_VERSION="13"
- OS_CODENAME="trixie"
- OS_DISPLAY="Debian 13 (Trixie)"
- ;;
- ubuntu2404)
- OS_TYPE="ubuntu"
- OS_VERSION="24.04"
- OS_CODENAME="noble"
- OS_DISPLAY="Ubuntu 24.04 LTS"
- ;;
- esac
- echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
- else
- exit-script
- fi
+ if OS_CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT OS" --radiolist \
+ "Choose Operating System for UniFi OS VM" 12 68 2 \
+ "debian13" "Debian 13 (Trixie) - Latest" ON \
+ "ubuntu2404" "Ubuntu 24.04 LTS (Noble)" OFF \
+ 3>&1 1>&2 2>&3); then
+ case $OS_CHOICE in
+ debian13)
+ OS_TYPE="debian"
+ OS_VERSION="13"
+ OS_CODENAME="trixie"
+ OS_DISPLAY="Debian 13 (Trixie)"
+ ;;
+ ubuntu2404)
+ OS_TYPE="ubuntu"
+ OS_VERSION="24.04"
+ OS_CODENAME="noble"
+ OS_DISPLAY="Ubuntu 24.04 LTS"
+ ;;
+ esac
+ echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
+ else
+ exit-script
+ fi
}
function select_cloud_init() {
- # Ubuntu only has cloudimg variant (always Cloud-Init), so no choice needed
- if [ "$OS_TYPE" = "ubuntu" ]; then
- USE_CLOUD_INIT="yes"
- echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (Ubuntu requires Cloud-Init)${CL}"
- return
- fi
+ # Ubuntu only has cloudimg variant (always Cloud-Init), so no choice needed
+ if [ "$OS_TYPE" = "ubuntu" ]; then
+ USE_CLOUD_INIT="yes"
+ echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (Ubuntu requires Cloud-Init)${CL}"
+ return
+ fi
- # Debian has two image variants, so user can choose
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \
- --yesno "Enable Cloud-Init for VM configuration?\n\nCloud-Init allows automatic configuration of:\n• User accounts and passwords\n• SSH keys\n• Network settings (DHCP/Static)\n• DNS configuration\n\nYou can also configure these settings later in Proxmox UI.\n\nNote: Debian without Cloud-Init will use nocloud image with console auto-login." 18 68); then
- USE_CLOUD_INIT="yes"
- echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes${CL}"
- else
- USE_CLOUD_INIT="no"
- echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}no${CL}"
- fi
+ # Debian has two image variants, so user can choose
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \
+ --yesno "Enable Cloud-Init for VM configuration?\n\nCloud-Init allows automatic configuration of:\n• User accounts and passwords\n• SSH keys\n• Network settings (DHCP/Static)\n• DNS configuration\n\nYou can also configure these settings later in Proxmox UI.\n\nNote: Debian without Cloud-Init will use nocloud image with console auto-login." 18 68); then
+ USE_CLOUD_INIT="yes"
+ echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes${CL}"
+ else
+ USE_CLOUD_INIT="no"
+ echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}no${CL}"
+ fi
}
function get_image_url() {
- local arch=$(dpkg --print-architecture)
- case $OS_TYPE in
- debian)
- # Debian has two variants:
- # - generic: For Cloud-Init enabled VMs
- # - nocloud: For VMs without Cloud-Init (has console auto-login)
- if [ "$USE_CLOUD_INIT" = "yes" ]; then
- echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-generic-${arch}.qcow2"
- else
- echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-nocloud-${arch}.qcow2"
- fi
- ;;
- ubuntu)
- # Ubuntu only has cloudimg variant (always with Cloud-Init support)
- echo "https://cloud-images.ubuntu.com/${OS_CODENAME}/current/${OS_CODENAME}-server-cloudimg-${arch}.img"
- ;;
- esac
+ local arch=$(dpkg --print-architecture)
+ case $OS_TYPE in
+ debian)
+ # Debian has two variants:
+ # - generic: For Cloud-Init enabled VMs
+ # - nocloud: For VMs without Cloud-Init (has console auto-login)
+ if [ "$USE_CLOUD_INIT" = "yes" ]; then
+ echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-generic-${arch}.qcow2"
+ else
+ echo "https://cloud.debian.org/images/cloud/${OS_CODENAME}/latest/debian-${OS_VERSION}-nocloud-${arch}.qcow2"
+ fi
+ ;;
+ ubuntu)
+ # Ubuntu only has cloudimg variant (always with Cloud-Init support)
+ echo "https://cloud-images.ubuntu.com/${OS_CODENAME}/current/${OS_CODENAME}-server-cloudimg-${arch}.img"
+ ;;
+ esac
}
function default_settings() {
- # OS Selection - ALWAYS ask
- select_os
+ # OS Selection - ALWAYS ask
+ select_os
- # Cloud-Init Selection - ALWAYS ask
- select_cloud_init
+ # Cloud-Init Selection - ALWAYS ask
+ select_cloud_init
- # Set defaults for other settings
- VMID=$(get_valid_nextid)
- FORMAT=""
- MACHINE=" -machine q35"
- DISK_CACHE=""
- DISK_SIZE="32G"
- HN="unifi-server-os"
- CPU_TYPE=" -cpu host"
- CORE_COUNT="2"
- RAM_SIZE="4096"
- BRG="vmbr0"
- MAC="$GEN_MAC"
- VLAN=""
- MTU=""
- START_VM="yes"
- METHOD="default"
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- echo -e "${CREATING}${BOLD}${DGN}Creating a UniFi OS VM using the above default settings${CL}"
+ # Set defaults for other settings
+ VMID=$(get_valid_nextid)
+ FORMAT=""
+ MACHINE=" -machine q35"
+ DISK_CACHE=""
+ DISK_SIZE="32G"
+ HN="unifi-server-os"
+ CPU_TYPE=" -cpu host"
+ CORE_COUNT="2"
+ RAM_SIZE="4096"
+ BRG="vmbr0"
+ MAC="$GEN_MAC"
+ VLAN=""
+ MTU=""
+ START_VM="yes"
+ METHOD="default"
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ echo -e "${CREATING}${BOLD}${DGN}Creating a UniFi OS VM using the above default settings${CL}"
}
function advanced_settings() {
- METHOD="advanced"
+ METHOD="advanced"
- # OS Selection - ALWAYS ask
- select_os
+ # OS Selection - ALWAYS ask
+ select_os
- # Cloud-Init Selection - ALWAYS ask
- select_cloud_init
+ # Cloud-Init Selection - ALWAYS ask
+ select_cloud_init
- [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
- while true; do
- if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z "$VMID" ]; then
- VMID=$(get_valid_nextid)
- fi
- if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
- echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
- sleep 2
- continue
- fi
- echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
- break
+ [ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
+ while true; do
+ if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z "$VMID" ]; then
+ VMID=$(get_valid_nextid)
+ fi
+ if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
+ echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
+ sleep 2
+ continue
+ fi
+ echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
+ break
+ else
+ exit-script
+ fi
+ done
+
+ if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
+ "q35" "Q35 (Modern, PCIe, UEFI)" ON \
+ "i440fx" "i440fx (Legacy)" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ "$MACH" = "q35" ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
+ fi
else
- exit-script
+ exit-script
fi
- done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
- "q35" "Q35 (Modern, PCIe, UEFI)" ON \
- "i440fx" "i440fx (Legacy)" OFF \
- 3>&1 1>&2 2>&3); then
- if [ "$MACH" = "q35" ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
+ if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
+ if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
+ DISK_SIZE="${DISK_SIZE}G"
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ else
+ echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
+ exit-script
+ fi
else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
- if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
- DISK_SIZE="${DISK_SIZE}G"
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
- elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
+ if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
+ "0" "None (Default)" ON \
+ "1" "Write Through" OFF \
+ 3>&1 1>&2 2>&3); then
+ if [ $DISK_CACHE = "1" ]; then
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
+ DISK_CACHE="cache=writethrough,"
+ else
+ echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
+ DISK_CACHE=""
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
- exit-script
+ exit-script
fi
- else
- exit-script
- fi
- if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
- "0" "None (Default)" ON \
- "1" "Write Through" OFF \
- 3>&1 1>&2 2>&3); then
- if [ $DISK_CACHE = "1" ]; then
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
- DISK_CACHE="cache=writethrough,"
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VM_NAME ]; then
+ HN="unifi-os-server"
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ else
+ HN=$(echo ${VM_NAME,,} | tr -d ' ')
+ echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ fi
else
- echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
- DISK_CACHE=""
+ exit-script
fi
- else
- exit-script
- fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VM_NAME ]; then
- HN="unifi-os-server"
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 10 58 2 \
+ "Host" "Host (Faster, recommended)" ON \
+ "KVM64" "KVM64 (Compatibility)" OFF \
+ 3>&1 1>&2 2>&3); then
+ case "$CPU_TYPE1" in
+ Host)
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
+ CPU_TYPE=" -cpu host"
+ ;;
+ *)
+ echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
+ CPU_TYPE=""
+ ;;
+ esac
else
- HN=$(echo ${VM_NAME,,} | tr -d ' ')
- echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 10 58 2 \
- "Host" "Host (Faster, recommended)" ON \
- "KVM64" "KVM64 (Compatibility)" OFF \
- 3>&1 1>&2 2>&3); then
- case "$CPU_TYPE1" in
- Host)
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
- CPU_TYPE=" -cpu host"
- ;;
- *)
- echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
- CPU_TYPE=""
- ;;
- esac
- else
- exit-script
- fi
-
- if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $CORE_COUNT ]; then
- CORE_COUNT="2"
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $CORE_COUNT ]; then
+ CORE_COUNT="2"
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ else
+ echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ fi
else
- echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $RAM_SIZE ]; then
- RAM_SIZE="2048"
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $RAM_SIZE ]; then
+ RAM_SIZE="2048"
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ else
+ echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ fi
else
- echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $BRG ]; then
- BRG="vmbr0"
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $BRG ]; then
+ BRG="vmbr0"
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ else
+ echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ fi
else
- echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MAC1 ]; then
- MAC="$GEN_MAC"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MAC1 ]; then
+ MAC="$GEN_MAC"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
+ else
+ MAC="$MAC1"
+ echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ fi
else
- MAC="$MAC1"
- echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $VLAN1 ]; then
- VLAN1="Default"
- VLAN=""
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $VLAN1 ]; then
+ VLAN1="Default"
+ VLAN=""
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ else
+ VLAN=",tag=$VLAN1"
+ echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ fi
else
- VLAN=",tag=$VLAN1"
- echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
- if [ -z $MTU1 ]; then
- MTU1="Default"
- MTU=""
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if [ -z $MTU1 ]; then
+ MTU1="Default"
+ MTU=""
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ else
+ MTU=",mtu=$MTU1"
+ echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ fi
else
- MTU=",mtu=$MTU1"
- echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
+ exit-script
fi
- else
- exit-script
- fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
- START_VM="yes"
- else
- echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
- START_VM="no"
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
+ START_VM="yes"
+ else
+ echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
+ START_VM="no"
+ fi
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Unifi OS VM?" --no-button Do-Over 10 58); then
- echo -e "${CREATING}${BOLD}${DGN}Creating a Unifi OS VM using the above advanced settings${CL}"
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Unifi OS VM?" --no-button Do-Over 10 58); then
+ echo -e "${CREATING}${BOLD}${DGN}Creating a Unifi OS VM using the above advanced settings${CL}"
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
function start_script() {
- if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
- header_info
- echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
- default_settings
- else
- header_info
- echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
- advanced_settings
- fi
+ if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
+ header_info
+ echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
+ default_settings
+ else
+ header_info
+ echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
+ advanced_settings
+ fi
}
check_root
arch_check
@@ -525,31 +525,31 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
- TAG=$(echo $line | awk '{print $1}')
- TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
- ITEM=" Type: $TYPE Free: $FREE "
- OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
- MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
- STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
+ TAG=$(echo $line | awk '{print $1}')
+ TYPE=$(echo $line | awk '{printf "%-10s", $2}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ ITEM=" Type: $TYPE Free: $FREE "
+ OFFSET=2
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
+ fi
+ STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
- msg_error "Unable to detect a valid storage location."
- exit
+ msg_error "Unable to detect a valid storage location."
+ exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
- STORAGE=${STORAGE_MENU[0]}
+ STORAGE=${STORAGE_MENU[0]}
else
- while [ -z "${STORAGE:+x}" ]; do
- #if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
- printf "\e[?25h"
- STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
- "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
- 16 $(($MSG_MAX_LENGTH + 23)) 6 \
- "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
- done
+ while [ -z "${STORAGE:+x}" ]; do
+ #if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
+ printf "\e[?25h"
+ STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
+ "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
+ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
+ "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
+ done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
@@ -559,9 +559,9 @@ msg_info "Fetching latest UniFi OS Server version"
# Install jq if not available
if ! command -v jq &>/dev/null; then
- msg_info "Installing jq for JSON parsing"
- apt-get update -qq >/dev/null 2>&1
- apt-get install -y jq -qq >/dev/null 2>&1
+ msg_info "Installing jq for JSON parsing"
+ apt-get update -qq >/dev/null 2>&1
+ apt-get install -y jq -qq >/dev/null 2>&1
fi
# Download firmware list from Ubiquiti API
@@ -569,9 +569,9 @@ API_URL="https://fw-update.ui.com/api/firmware-latest"
TEMP_JSON=$(mktemp)
if ! curl -fsSL "$API_URL" -o "$TEMP_JSON"; then
- rm -f "$TEMP_JSON"
- msg_error "Failed to fetch data from Ubiquiti API"
- exit 1
+ rm -f "$TEMP_JSON"
+ msg_error "Failed to fetch data from Ubiquiti API"
+ exit 1
fi
# Parse JSON to find latest unifi-os-server linux-x64 version
@@ -590,8 +590,8 @@ UOS_URL=$(echo "$LATEST" | jq -r '._links.data.href')
rm -f "$TEMP_JSON"
if [ -z "$UOS_URL" ] || [ -z "$UOS_VERSION" ]; then
- msg_error "Failed to parse UniFi OS Server version or download URL"
- exit 1
+ msg_error "Failed to parse UniFi OS Server version or download URL"
+ exit 1
fi
UOS_INSTALLER="unifi-os-server-${UOS_VERSION}.bin"
@@ -609,10 +609,10 @@ msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
# --- Inject UniFi Installer ---
if ! command -v virt-customize &>/dev/null; then
- msg_info "Installing libguestfs-tools on host"
- apt-get -qq update >/dev/null
- apt-get -qq install libguestfs-tools -y >/dev/null
- msg_ok "Installed libguestfs-tools"
+ msg_info "Installing libguestfs-tools on host"
+ apt-get -qq update >/dev/null
+ apt-get -qq install libguestfs-tools -y >/dev/null
+ msg_ok "Installed libguestfs-tools"
fi
msg_info "Preparing ${OS_DISPLAY} Qcow2 Disk Image"
@@ -775,16 +775,16 @@ UNIFI_PREINSTALLED="no"
msg_info "Pre-installing base packages (qemu-guest-agent, podman, curl)"
if virt-customize -a "${FILE}" --install qemu-guest-agent,curl,ca-certificates,podman,uidmap,slirp4netns >/dev/null 2>&1; then
- msg_ok "Pre-installed base packages (UniFi OS will install on first boot)"
+ msg_ok "Pre-installed base packages (UniFi OS will install on first boot)"
else
- msg_info "Pre-installation not possible, packages will install on first boot"
+ msg_info "Pre-installation not possible, packages will install on first boot"
fi
# Add auto-login if Cloud-Init is disabled
if [ "$USE_CLOUD_INIT" != "yes" ]; then
- virt-customize -q -a "${FILE}" \
- --run-command 'mkdir -p /etc/systemd/system/getty@tty1.service.d' \
- --run-command "bash -c 'echo -e \"[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin root --noclear %I \\\$TERM\" > /etc/systemd/system/getty@tty1.service.d/override.conf'" 2>/dev/null
+ virt-customize -q -a "${FILE}" \
+ --run-command 'mkdir -p /etc/systemd/system/getty@tty1.service.d' \
+ --run-command "bash -c 'echo -e \"[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin root --noclear %I \\\$TERM\" > /etc/systemd/system/getty@tty1.service.d/override.conf'" 2>/dev/null
fi
msg_ok "UniFi OS Server will be installed on first boot"
@@ -796,7 +796,7 @@ qemu-img create -f qcow2 expanded.qcow2 ${DISK_SIZE} >/dev/null 2>&1
# Detect partition device (sda1 for Ubuntu, vda1 for Debian)
PARTITION_DEV=$(virt-filesystems --long -h --all -a "${FILE}" | grep -oP '/dev/\K(s|v)da1' | head -1)
if [ -z "$PARTITION_DEV" ]; then
- PARTITION_DEV="sda1" # fallback
+ PARTITION_DEV="sda1" # fallback
fi
virt-resize --quiet --expand /dev/${PARTITION_DEV} ${FILE} expanded.qcow2 >/dev/null 2>&1
@@ -805,35 +805,35 @@ msg_ok "Expanded disk image to ${DISK_SIZE}"
msg_info "Creating UniFi OS VM"
qm create "$VMID" -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf \
- ${CPU_TYPE} -cores "$CORE_COUNT" -memory "$RAM_SIZE" \
- -name "$HN" -tags community-script \
- -net0 virtio,bridge="$BRG",macaddr="$MAC""$VLAN""$MTU" \
- -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
+ ${CPU_TYPE} -cores "$CORE_COUNT" -memory "$RAM_SIZE" \
+ -name "$HN" -tags community-script \
+ -net0 virtio,bridge="$BRG",macaddr="$MAC""$VLAN""$MTU" \
+ -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc "$STORAGE" "$VMID" "vm-$VMID-disk-0" 4M >/dev/null
IMPORT_OUT="$(qm importdisk "$VMID" "$FILE" "$STORAGE" --format qcow2 2>&1 || true)"
DISK_REF="$(printf '%s\n' "$IMPORT_OUT" | sed -n "s/.*successfully imported disk '\([^']\+\)'.*/\1/p")"
if [[ -z "$DISK_REF" ]]; then
- DISK_REF="$(pvesm list "$STORAGE" | awk -v id="$VMID" '$1 ~ ("vm-"id"-disk-") {print $1}' | sort | tail -n1)"
+ DISK_REF="$(pvesm list "$STORAGE" | awk -v id="$VMID" '$1 ~ ("vm-"id"-disk-") {print $1}' | sort | tail -n1)"
fi
qm set "$VMID" \
- -efidisk0 "${STORAGE}:0${FORMAT},size=4M" \
- -scsi0 "${DISK_REF},${DISK_CACHE}size=${DISK_SIZE}" \
- -boot order=scsi0 -serial0 socket >/dev/null
+ -efidisk0 "${STORAGE}:0${FORMAT},size=4M" \
+ -scsi0 "${DISK_REF},${DISK_CACHE}size=${DISK_SIZE}" \
+ -boot order=scsi0 -serial0 socket >/dev/null
qm resize "$VMID" scsi0 "$DISK_SIZE" >/dev/null
qm set "$VMID" --agent enabled=1 >/dev/null
# Add Cloud-Init drive if enabled
if [ "$USE_CLOUD_INIT" = "yes" ]; then
- msg_info "Configuring Cloud-Init"
- setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes" >/dev/null 2>&1
- msg_ok "Cloud-Init configured"
+ msg_info "Configuring Cloud-Init"
+ setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes" >/dev/null 2>&1
+ msg_ok "Cloud-Init configured"
fi
DESCRIPTION=$(
- cat <
@@ -869,71 +869,71 @@ msg_info "Operating System: ${OS_DISPLAY}"
msg_info "Cloud-Init: ${USE_CLOUD_INIT}"
if [ "$START_VM" == "yes" ]; then
- msg_info "Starting UniFi OS VM"
- qm start $VMID
- msg_ok "Started UniFi OS VM"
+ msg_info "Starting UniFi OS VM"
+ qm start $VMID
+ msg_ok "Started UniFi OS VM"
- msg_info "Waiting for VM to boot (30 seconds)"
- sleep 30
- msg_ok "VM should be booting now"
+ msg_info "Waiting for VM to boot (30 seconds)"
+ sleep 30
+ msg_ok "VM should be booting now"
- msg_info "Detecting VM IP address (may take up to 60 seconds)"
- VM_IP=""
- for i in {1..30}; do
- VM_IP=$(qm guest cmd $VMID network-get-interfaces 2>/dev/null | jq -r '.[1]["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | grep -v "127.0.0.1" | head -1 || echo "")
+ msg_info "Detecting VM IP address (may take up to 60 seconds)"
+ VM_IP=""
+ for i in {1..30}; do
+ VM_IP=$(qm guest cmd $VMID network-get-interfaces 2>/dev/null | jq -r '.[1]["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | grep -v "127.0.0.1" | head -1 || echo "")
- if [ -n "$VM_IP" ]; then
- msg_ok "VM IP Address detected: ${VM_IP}"
- break
- fi
- sleep 2
- done
-
- if [ -n "$VM_IP" ]; then
- msg_info "Waiting for UniFi OS installation to complete (this takes 3-5 minutes)"
-
- WAIT_COUNT=0
- MAX_WAIT=300 # 5 minutes max
- PORT_OPEN=0
- LAST_MSG_TIME=0
-
- while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
- if timeout 2 bash -c ">/dev/tcp/${VM_IP}/11443" 2>/dev/null; then
- PORT_OPEN=1
- msg_ok "UniFi OS Server installation completed successfully"
- break
- fi
-
- sleep 5
- WAIT_COUNT=$((WAIT_COUNT + 5))
-
- # Update message every 20 seconds
- if [ $((WAIT_COUNT - LAST_MSG_TIME)) -ge 20 ]; then
- echo -e "${BFR}${TAB}${YW}${HOLD}Installation in progress... ${WAIT_COUNT}s elapsed (check: tail -f /var/log/install-unifi.log in VM)${CL}"
- LAST_MSG_TIME=$WAIT_COUNT
- fi
+ if [ -n "$VM_IP" ]; then
+ msg_ok "VM IP Address detected: ${VM_IP}"
+ break
+ fi
+ sleep 2
done
- if [ $PORT_OPEN -eq 1 ]; then
- echo -e "\n${TAB}${GATEWAY}${BOLD}${GN}✓ UniFi OS Server is ready!${CL}"
- echo -e "${TAB}${GATEWAY}${BOLD}${GN}✓ Access at: ${BGN}https://${VM_IP}:11443${CL}\n"
+ if [ -n "$VM_IP" ]; then
+ msg_info "Waiting for UniFi OS installation to complete (this takes 3-5 minutes)"
+
+ WAIT_COUNT=0
+ MAX_WAIT=300 # 5 minutes max
+ PORT_OPEN=0
+ LAST_MSG_TIME=0
+
+ while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
+ if timeout 2 bash -c ">/dev/tcp/${VM_IP}/11443" 2>/dev/null; then
+ PORT_OPEN=1
+ msg_ok "UniFi OS Server installation completed successfully"
+ break
+ fi
+
+ sleep 5
+ WAIT_COUNT=$((WAIT_COUNT + 5))
+
+ # Update message every 20 seconds
+ if [ $((WAIT_COUNT - LAST_MSG_TIME)) -ge 20 ]; then
+ echo -e "${BFR}${TAB}${YW}${HOLD}Installation in progress... ${WAIT_COUNT}s elapsed (check: tail -f /var/log/install-unifi.log in VM)${CL}"
+ LAST_MSG_TIME=$WAIT_COUNT
+ fi
+ done
+
+ if [ $PORT_OPEN -eq 1 ]; then
+ echo -e "\n${TAB}${GATEWAY}${BOLD}${GN}✓ UniFi OS Server is ready!${CL}"
+ echo -e "${TAB}${GATEWAY}${BOLD}${GN}✓ Access at: ${BGN}https://${VM_IP}:11443${CL}\n"
+ else
+ msg_ok "VM is running, but installation is still in progress"
+ echo -e "${TAB}${INFO}${YW}Installation takes 3-5 minutes after first boot${CL}"
+ echo -e "${TAB}${INFO}${YW}Check progress: ${BL}qm guest exec ${VMID} -- tail -f /var/log/install-unifi.log${CL}"
+ echo -e "${TAB}${INFO}${YW}Or SSH to: ${BL}${VM_IP}${CL} and run: ${BL}tail -f /var/log/install-unifi.log${CL}"
+ echo -e "${TAB}${INFO}${YW}Access will be at: ${BGN}https://${VM_IP}:11443${CL}"
+ fi
else
- msg_ok "VM is running, but installation is still in progress"
- echo -e "${TAB}${INFO}${YW}Installation takes 3-5 minutes after first boot${CL}"
- echo -e "${TAB}${INFO}${YW}Check progress: ${BL}qm guest exec ${VMID} -- tail -f /var/log/install-unifi.log${CL}"
- echo -e "${TAB}${INFO}${YW}Or SSH to: ${BL}${VM_IP}${CL} and run: ${BL}tail -f /var/log/install-unifi.log${CL}"
- echo -e "${TAB}${INFO}${YW}Access will be at: ${BGN}https://${VM_IP}:11443${CL}"
+ msg_ok "VM is running (ID: ${VMID})"
+ echo -e "${TAB}${INFO}${YW}Could not auto-detect IP address${CL}"
+ echo -e "${TAB}${INFO}${YW}Access VM console in Proxmox to check status${CL}"
+ echo -e "${TAB}${INFO}${YW}Or check installation log: ${BL}tail -f /var/log/install-unifi.log${CL}"
fi
- else
- msg_ok "VM is running (ID: ${VMID})"
- echo -e "${TAB}${INFO}${YW}Could not auto-detect IP address${CL}"
- echo -e "${TAB}${INFO}${YW}Access VM console in Proxmox to check status${CL}"
- echo -e "${TAB}${INFO}${YW}Or check installation log: ${BL}tail -f /var/log/install-unifi.log${CL}"
- fi
fi
if [ "$USE_CLOUD_INIT" = "yes" ]; then
- display_cloud_init_info "$VMID" "$HN"
+ display_cloud_init_info "$VMID" "$HN"
fi
post_update_to_api "done" "none"