Compare commits

..

1 Commits

Author SHA1 Message Date
MickLesk
0a8426d0c0 navidrome: restore data folder ownership on install and update
Upstream's deb postinstall runs chown navidrome:navidrome on
/var/lib/navidrome/cache without -R, and only behind an .installed
flag, so it never runs again on an upgrade. Every navidrome command
the packaging invokes as root creates cache content owned by root,
which the service then cannot write as the navidrome user - artwork
that was already cached keeps working while newly resolved album and
playlist covers fail.

Reassert ownership of the data folder after deploying the release.
The music folder is left alone, it is commonly a bind mount.
2026-09-14 16:03:47 +02:00
12 changed files with 545 additions and 414 deletions

View File

@@ -543,29 +543,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-09-15
### 🆕 New Scripts
- valhalla ([#17231](https://github.com/community-scripts/ProxmoxVE/pull/17231))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- tracearr: copy packages/emails into the deploy tree [@connorgallopo](https://github.com/connorgallopo) ([#17268](https://github.com/community-scripts/ProxmoxVE/pull/17268))
- Immich: Pin to v3.2.1 [@vhsdream](https://github.com/vhsdream) ([#17264](https://github.com/community-scripts/ProxmoxVE/pull/17264))
### 💾 Core
- Releases: rank releases on their numbers, not on sort -V over the raw tag [@MickLesk](https://github.com/MickLesk) ([core#39](https://github.com/community-scripts/core/pull/39))
### 🧰 Tools
- #### 🔧 Refactor
- Refactor: monitor-all (decide on flag values, not on key presence) [@MickLesk](https://github.com/MickLesk) ([#17261](https://github.com/community-scripts/ProxmoxVE/pull/17261))
## 2026-09-14
### 🆕 New Scripts

View File

@@ -1,6 +0,0 @@
_ __ ____ ____
| | / /___ _/ / /_ ____ _/ / /___ _
| | / / __ `/ / __ \/ __ `/ / / __ `/
| |/ / /_/ / / / / / /_/ / / / /_/ /
|___/\__,_/_/_/ /_/\__,_/_/_/\__,_/

View File

@@ -112,7 +112,7 @@ EOF
msg_ok "Image-processing libraries up to date"
fi
RELEASE="v3.2.1"
RELEASE="v3.2.0"
if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
if [[ $(cat ~/.immich) > "2.5.1" ]]; then
msg_info "Enabling Maintenance Mode"

View File

@@ -38,6 +38,15 @@ function update_script() {
fetch_and_deploy_gh_release "navidrome" "navidrome/navidrome" "binary"
# The upstream postinstall only chowns the cache directory itself, and only
# on the very first install, so root-owned subdirectories survive upgrades
# and the service can no longer write its artwork there.
if id -u navidrome >/dev/null 2>&1; then
msg_info "Fixing Data Folder Ownership"
chown -R navidrome:navidrome /var/lib/navidrome
msg_ok "Fixed Data Folder Ownership"
fi
msg_info "Starting Services"
systemctl start navidrome
msg_ok "Started Services"

View File

@@ -124,7 +124,7 @@ EOF
$STD pnpm turbo telemetry disable
$STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
rm -rf /opt/tracearr
mkdir -p /opt/tracearr/{packages/shared,packages/emails,apps/server,apps/web,apps/server/src/db}
mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db}
cp -rf package.json /opt/tracearr/
cp -rf pnpm-workspace.yaml /opt/tracearr/
cp -rf pnpm-lock.yaml /opt/tracearr/
@@ -134,8 +134,6 @@ EOF
cp -rf apps/web/dist /opt/tracearr/apps/web/dist
cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
cp -rf packages/emails/package.json /opt/tracearr/packages/emails/
cp -rf packages/emails/dist /opt/tracearr/packages/emails/dist
cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
cp -rf data /opt/tracearr/data
mkdir -p /opt/tracearr/data/image-cache

View File

@@ -1,104 +0,0 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/valhalla/valhalla
APP="Valhalla"
var_tags="${var_tags:-mapping;routing}"
var_cpu="${var_cpu:-6}"
var_ram="${var_ram:-6144}"
var_disk="${var_disk:-24}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/valhalla.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "prime_server" "kevinkreiser/prime_server"; then
RELEASE="$CHECK_UPDATE_RELEASE"
msg_info "Stopping Service"
systemctl stop valhalla
msg_ok "Stopped Service"
msg_info "Building prime_server ${RELEASE} (Patience)"
rm -rf /tmp/prime_server
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/kevinkreiser/prime_server /tmp/prime_server
cd /tmp/prime_server
$STD ./autogen.sh
$STD ./configure
$STD make -j"$(nproc)"
$STD make install
cd /
rm -rf /tmp/prime_server
ldconfig
echo "${RELEASE#v}" >"$HOME/.prime_server"
msg_ok "Built prime_server ${RELEASE}"
msg_info "Starting Service"
systemctl start valhalla
msg_ok "Started Service"
fi
if check_for_gh_release "valhalla" "valhalla/valhalla"; then
RELEASE="$CHECK_UPDATE_RELEASE"
msg_info "Stopping Service"
systemctl stop valhalla
msg_ok "Stopped Service"
msg_info "Fetching Valhalla ${RELEASE} (Patience)"
rm -rf /opt/valhalla
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/valhalla/valhalla.git /opt/valhalla
msg_ok "Fetched Valhalla ${RELEASE}"
msg_info "Compiling Valhalla ${RELEASE} (this takes 20-45+ minutes, be patient)"
MEM_MB=$(awk '/MemTotal/{print int($2/1024)}' /proc/meminfo)
BUILD_JOBS=$((MEM_MB / 2000))
[[ $BUILD_JOBS -lt 1 ]] && BUILD_JOBS=1
[[ $BUILD_JOBS -gt $(nproc) ]] && BUILD_JOBS=$(nproc)
cd /opt/valhalla
$STD cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DENABLE_SINGLE_FILES_WERROR=OFF
$STD cmake --build build -- -j"$BUILD_JOBS"
$STD cmake --install build
ldconfig
echo "${RELEASE#v}" >"$HOME/.valhalla"
msg_ok "Compiled Valhalla ${RELEASE}"
msg_info "Starting Service"
systemctl start valhalla
msg_ok "Started Service"
fi
msg_ok "Updated Successfully!\n"
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 "${GATEWAY}${BGN}http://${IP}:8002/status${CL}"
echo -e "${INFO}${YW}No routing tiles are built yet. Build them for your region with:${CL}"
echo -e "${TAB}${BGN}/opt/valhalla_data/build-tiles.sh https://download.geofabrik.de/<continent>/<region>-latest.osm.pbf${CL}"

View File

@@ -353,7 +353,7 @@ ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.2.1" "$SRC_DIR"
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.2.0" "$SRC_DIR"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs

View File

@@ -19,6 +19,10 @@ msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "navidrome" "navidrome/navidrome" "binary"
if id -u navidrome >/dev/null 2>&1; then
chown -R navidrome:navidrome /var/lib/navidrome
fi
msg_info "Starting Navidrome"
systemctl enable -q --now navidrome
msg_ok "Started Navidrome"

View File

@@ -67,7 +67,7 @@ cd /opt/tracearr.build
$STD pnpm install --frozen-lockfile --force
$STD pnpm turbo telemetry disable
$STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
mkdir -p /opt/tracearr/{packages/shared,packages/emails,apps/server,apps/web,apps/server/src/db}
mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db}
cp -rf package.json /opt/tracearr/
cp -rf pnpm-workspace.yaml /opt/tracearr/
cp -rf pnpm-lock.yaml /opt/tracearr/
@@ -77,8 +77,6 @@ cp -rf apps/server/scripts /opt/tracearr/apps/server/scripts
cp -rf apps/web/dist /opt/tracearr/apps/web/dist
cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
cp -rf packages/emails/package.json /opt/tracearr/packages/emails/
cp -rf packages/emails/dist /opt/tracearr/packages/emails/dist
cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
cp -rf data /opt/tracearr/data
mkdir -p /opt/tracearr/data/image-cache

View File

@@ -1,187 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/valhalla/valhalla
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 \
autoconf \
automake \
ccache \
clang \
clang-tidy \
coreutils \
cmake \
g++ \
gcc \
git \
jq \
lcov \
libboost-all-dev \
libcurl4-openssl-dev \
libczmq-dev \
libgdal-dev \
libgeos++-dev \
libgeos-dev \
libluajit-5.1-dev \
liblz4-dev \
libprotobuf-dev \
libspatialite-dev \
libsqlite3-dev \
libsqlite3-mod-spatialite \
libtool \
libzmq3-dev \
lld \
locales \
luajit \
make \
osmium-tool \
parallel \
pkgconf \
protobuf-compiler \
python3-all-dev \
python3-shapely \
python3-requests \
python3-pip \
spatialite-bin \
unzip \
zlib1g-dev
msg_ok "Installed Dependencies"
PRIME_SERVER_RELEASE=$(get_latest_github_release "kevinkreiser/prime_server" "false")
msg_info "Building prime_server ${PRIME_SERVER_RELEASE} (Patience)"
$STD git clone --recurse-submodules --depth 1 --branch "$PRIME_SERVER_RELEASE" https://github.com/kevinkreiser/prime_server /tmp/prime_server
cd /tmp/prime_server
$STD ./autogen.sh
$STD ./configure
$STD make -j"$(nproc)"
$STD make install
cd /
rm -rf /tmp/prime_server
echo "${PRIME_SERVER_RELEASE#v}" >"$HOME/.prime_server"
msg_ok "Built prime_server"
RELEASE=$(get_latest_github_release "valhalla/valhalla" "false")
msg_info "Cloning Valhalla ${RELEASE} (Patience)"
mkdir -p /opt/valhalla
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/valhalla/valhalla.git /opt/valhalla
msg_ok "Cloned Valhalla ${RELEASE}"
msg_info "Compiling Valhalla ${RELEASE} (this takes 20-45+ minutes, be patient)"
MEM_MB=$(awk '/MemTotal/{print int($2/1024)}' /proc/meminfo)
BUILD_JOBS=$((MEM_MB / 2000))
[[ $BUILD_JOBS -lt 1 ]] && BUILD_JOBS=1
[[ $BUILD_JOBS -gt $(nproc) ]] && BUILD_JOBS=$(nproc)
cd /opt/valhalla
$STD cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DENABLE_SINGLE_FILES_WERROR=OFF
$STD cmake --build build -- -j"$BUILD_JOBS"
$STD cmake --install build
ldconfig
echo "${RELEASE#v}" >"$HOME/.valhalla"
msg_ok "Compiled Valhalla ${RELEASE}"
msg_info "Configuring Valhalla"
useradd --system --no-create-home --shell /usr/sbin/nologin valhalla 2>/dev/null || true
mkdir -p /opt/valhalla_data/{valhalla_tiles,pbf}
THREADS=$(nproc)
valhalla_build_config \
--mjolnir-tile-dir /opt/valhalla_data/valhalla_tiles \
--mjolnir-tile-extract /opt/valhalla_data/valhalla_tiles.tar \
--mjolnir-admin /opt/valhalla_data/admins.sqlite \
--mjolnir-timezone /opt/valhalla_data/timezones.sqlite \
--mjolnir-concurrency "$THREADS" \
>/opt/valhalla_data/valhalla.json
cat <<'EOF' >/opt/valhalla_data/build-tiles.sh
#!/usr/bin/env bash
# (Re)builds Valhalla routing tiles from one or more OSM extracts.
# Usage: build-tiles.sh <pbf-url-or-path> [<pbf-url-or-path> ...]
# Example: build-tiles.sh https://download.geofabrik.de/europe/germany-latest.osm.pbf
set -euo pipefail
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <pbf-url-or-path> [<pbf-url-or-path> ...]" >&2
exit 1
fi
DATA_DIR=/opt/valhalla_data
CONFIG="$DATA_DIR/valhalla.json"
mkdir -p "$DATA_DIR/pbf"
FILES=()
for src in "$@"; do
if [[ "$src" == http://* || "$src" == https://* ]]; then
fname="$DATA_DIR/pbf/$(basename "$src")"
echo "Downloading $src"
curl -fL --progress-bar -o "$fname" "$src"
else
fname="$src"
fi
FILES+=("$fname")
done
systemctl stop valhalla
echo "Building admin database"
valhalla_build_admins --config "$CONFIG" "${FILES[@]}"
echo "Building timezone database"
valhalla_build_timezones >"$DATA_DIR/timezones.sqlite"
echo "Building initial tile graph"
valhalla_build_tiles -c "$CONFIG" -e build "${FILES[@]}"
echo "Enhancing tile graph"
valhalla_build_tiles -c "$CONFIG" -s enhance "${FILES[@]}"
echo "Packing tiles into a single extract"
valhalla_build_extract -c "$CONFIG" -v
chown -R valhalla:valhalla "$DATA_DIR"
systemctl start valhalla
echo "Done. Tiles are in $DATA_DIR/valhalla_tiles (and packed at $DATA_DIR/valhalla_tiles.tar)."
EOF
chmod +x /opt/valhalla_data/build-tiles.sh
chown -R valhalla:valhalla /opt/valhalla_data
msg_ok "Configured Valhalla"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/valhalla.service
[Unit]
Description=Valhalla Routing Engine
After=network.target
[Service]
Type=simple
User=valhalla
Group=valhalla
WorkingDirectory=/opt/valhalla_data
ExecStart=/usr/local/bin/valhalla_service /opt/valhalla_data/valhalla.json ${THREADS}
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now valhalla
msg_ok "Created Service"
if [[ -n "${VALHALLA_PBF_URLS:-}" ]]; then
msg_info "Building Initial Tiles from VALHALLA_PBF_URLS (this can take a long time)"
$STD /opt/valhalla_data/build-tiles.sh $VALHALLA_PBF_URLS
msg_ok "Built Initial Tiles"
fi
motd_ssh
customize
cleanup_lxc

View File

@@ -45,8 +45,6 @@ add() {
excluded_instances=("$@")
echo "Excluded instances: ${excluded_instances[@]}"
value_of() { sed -n "s/^$1:[[:space:]]*//p" <<<"$config" | head -n1; }
while true; do
for instance in $(pct list | awk 'NR>1 {print $1}'; qm list | awk 'NR>1 {print $1}'); do
@@ -61,21 +59,21 @@ while true; do
if [ -r "/etc/pve/lxc/$instance.conf" ]; then
type="ct"
config_file="/etc/pve/lxc/$instance.conf"
elif [ -r "/etc/pve/qemu-server/$instance.conf" ]; then
else
type="vm"
config_file="/etc/pve/qemu-server/$instance.conf"
else
echo "Skipping $instance because its config is no longer readable"
continue
fi
config=$(sed '/^\[/,$d' "$config_file")
# Both are booleans that Proxmox also writes as 0, so the value decides and
# not the presence of the key.
[ "$(value_of onboot)" = "1" ] && onboot="true" || onboot="false"
[ "$(value_of template)" = "1" ] && template="true" || template="false"
# Skip templates and onboot-disabled
if grep -q "onboot: 0" <<<"$config" || ! grep -q "onboot" <<<"$config"; then
onboot="true"
else
onboot="false"
fi
template=$(grep -q "^template:" <<<"$config" && echo "true" || echo "false")
if [ "$onboot" != "true" ]; then
if [ "$onboot" == "true" ]; then
echo "Skipping $instance because it is set not to boot"
continue
elif [ "$template" == "true" ]; then
@@ -83,40 +81,34 @@ while true; do
continue
fi
# Tags are semicolon separated, so match a whole entry instead of a
# substring of a longer tag such as mon-restart-disabled.
tags=";$(value_of tags | tr -d '[:space:]');"
if [[ "$tags" != *";mon-restart;"* ]]; then
# Check for mon-restart tag
has_tag=$(grep -q "tags:.*mon-restart" <<<"$config" && echo "true" || echo "false")
if [ "$has_tag" != "true" ]; then
echo "Skipping $instance because it does not have 'mon-restart' tag"
continue
fi
# Responsiveness check and restart if needed
if [ "$type" == "vm" ]; then
if ! qm status "$instance" 2>/dev/null | grep -q "status: running"; then
echo "$(date): VM $instance is not running, starting..."
qm start "$instance" >/dev/null 2>&1
elif qm guest cmd "$instance" ping >/dev/null 2>&1; then
# Check if guest agent responds
if qm guest cmd $instance ping >/dev/null 2>&1; then
echo "VM $instance is responsive via guest agent"
else
echo "$(date): VM $instance is not responding to agent ping, restarting..."
qm stop "$instance" >/dev/null 2>&1
sleep 5
qm start "$instance" >/dev/null 2>&1
if qm status $instance | grep -q "status: running"; then
qm stop $instance >/dev/null 2>&1
sleep 5
fi
qm start $instance >/dev/null 2>&1
fi
else
if ! pct status "$instance" 2>/dev/null | grep -q "status: running"; then
echo "$(date): CT $instance is not running, starting..."
pct start "$instance" >/dev/null 2>&1
continue
fi
# Not every container names its interface eth0.
IP=$(pct exec "$instance" -- ip -4 -o addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -n1)
if [ -z "$IP" ] || ! ping -c 1 -W 2 "$IP" >/dev/null 2>&1; then
# Container: get IP and ping
IP=$(pct exec $instance ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)
if ! ping -c 1 $IP >/dev/null 2>&1; then
echo "$(date): CT $instance is not responding, restarting..."
pct stop "$instance" >/dev/null 2>&1
pct stop $instance >/dev/null 2>&1
sleep 5
pct start "$instance" >/dev/null 2>&1
pct start $instance >/dev/null 2>&1
else
echo "CT $instance is responsive"
fi
@@ -132,18 +124,23 @@ EOF
touch /var/log/ping-instances.log
chmod +x /usr/local/bin/ping-instances.sh
# The service loops with its own five minute sleep, so the timer that earlier
# versions installed could only ever start a unit that was already running.
if [[ -f /etc/systemd/system/ping-instances.timer ]]; then
systemctl disable -q --now ping-instances.timer 2>/dev/null || true
rm -f /etc/systemd/system/ping-instances.timer
fi
cat <<EOF >/etc/systemd/system/ping-instances.timer
[Unit]
Description=Delay ping-instances.service by 5 minutes
[Timer]
OnBootSec=300
OnUnitActiveSec=300
[Install]
WantedBy=timers.target
EOF
cat <<EOF >/etc/systemd/system/ping-instances.service
[Unit]
Description=Ping instances every 5 minutes and restart if necessary
After=pve-cluster.service
Wants=pve-cluster.service
After=ping-instances.timer
Requires=ping-instances.timer
[Service]
Type=simple
@@ -161,6 +158,7 @@ WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable -q --now ping-instances.timer
systemctl enable -q --now ping-instances.service
clear
echo -e "\n Monitor All installed."
@@ -169,7 +167,7 @@ EOF
}
remove() {
systemctl disable -q --now ping-instances.timer 2>/dev/null || true
systemctl disable -q --now ping-instances.timer
systemctl disable -q --now ping-instances.service
rm -f /etc/systemd/system/ping-instances.service
rm -f /etc/systemd/system/ping-instances.timer

View File

@@ -1,26 +1,64 @@
#!/usr/bin/env bash
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: juronja
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.truenas.com/truenas-community-edition/
COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main}"
source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/pve/vm-core.func")
load_functions
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
function header_info() {
clear
cat <<"EOF"
______ _ _____ _____
/_ __/______ _____ / | / / | / ___/
/ / / ___/ / / / _ \/ |/ / /| | \__ \
/ / / / / /_/ / __/ /| / ___ |___/ /
/_/ /_/ \__,_/\___/_/ |_/_/ |_/____/
(Community Edition)
EOF
}
header_info
echo -e "\n Loading..."
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
METHOD=""
APP="TrueNAS"
APP_TYPE="vm"
NSAPP="truenas-vm"
header_info
echo -e "\n Loading..."
YW=$(echo "\033[33m")
BL=$(echo "\033[36m")
RD=$(echo "\033[01;31m")
BGN=$(echo "\033[4;92m")
GN=$(echo "\033[1;92m")
DGN=$(echo "\033[32m")
CL=$(echo "\033[m")
CL=$(echo "\033[m")
BOLD=$(echo "\033[1m")
BFR="\\r\\033[K"
HOLD=" "
TAB=" "
CM="${TAB}✔️${TAB}${CL}"
CROSS="${TAB}✖️${TAB}${CL}"
INFO="${TAB}💡${TAB}${CL}"
OS="${TAB}🖥️${TAB}${CL}"
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
ISO="${TAB}📀${TAB}${CL}"
DISKSIZE="${TAB}💾${TAB}${CL}"
CPUCORE="${TAB}🧠${TAB}${CL}"
RAMSIZE="${TAB}🛠️${TAB}${CL}"
CONTAINERID="${TAB}🆔${TAB}${CL}"
HOSTNAME="${TAB}🏠${TAB}${CL}"
BRIDGE="${TAB}🌉${TAB}${CL}"
GATEWAY="${TAB}🌐${TAB}${CL}"
DISK="${TAB}💽${TAB}${CL}"
DEFAULT="${TAB}⚙️${TAB}${CL}"
MACADDRESS="${TAB}🔗${TAB}${CL}"
VLANTAG="${TAB}🏷️${TAB}${CL}"
CREATING="${TAB}🚀${TAB}${CL}"
ADVANCED="${TAB}🧩${TAB}${CL}"
CLOUD="${TAB}☁️${TAB}${CL}"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
@@ -28,6 +66,15 @@ trap cleanup EXIT
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
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
}
function truenas_iso_lookup() {
local BASE_URL="https://download.truenas.com"
@@ -53,7 +100,7 @@ function truenas_iso_lookup() {
pre_releases+=("$path")
else
local major_version=$(echo "$version" | cut -d'.' -f1,2)
local current_stored_path=${latest_stables["$major_version"]:-}
local current_stored_path=${latest_stables["$major_version"]}
if [[ -z "$current_stored_path" ]]; then
latest_stables["$major_version"]="$path"
else
@@ -74,17 +121,135 @@ function truenas_iso_lookup() {
done | sort -V
}
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"
}
function cleanup_vmid() {
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
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "TrueNAS VM" --yesno "This will create a New TrueNAS VM. Proceed?" 10 58; then
:
else
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}"
}
function msg_ok() {
local msg="$1"
echo -e "${BFR}${CM}${GN}${msg}${CL}"
}
function msg_error() {
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
}
function pve_check() {
local PVE_VER
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
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 105
fi
return 0
fi
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}"
if ((MINOR < 0 || MINOR > 2)); then
msg_error "This version of Proxmox VE is not yet supported."
msg_error "Supported: Proxmox VE version 9.0 9.2"
exit 105
fi
return 0
fi
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported versions: Proxmox VE 8.0 8.x or 9.0 9.2"
exit 105
}
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
}
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
fi
}
function exit-script() {
clear
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
exit
}
function default_settings() {
VMID=$(get_valid_nextid)
ISO_DEFAULT="latest stable"
vm_apply_machine_type "q35"
FORMAT=""
MACHINE="q35"
DISK_SIZE="16"
DISK_CACHE=""
HN="truenas"
CPU_TYPE=" -cpu host"
CPU_TYPE="host"
CORE_COUNT="2"
RAM_SIZE="8192"
BRG="vmbr0"
@@ -92,38 +257,242 @@ function default_settings() {
VLAN=""
MTU=""
START_VM="yes"
IMPORT_DISKS="no"
METHOD="default"
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
echo -e "${ISO}${BOLD}${DGN}ISO Chosen: ${BGN}${ISO_DEFAULT}${CL}"
vm_echo_default_settings
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}${MACHINE}${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}${CPU_TYPE}${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 TrueNAS VM using the above default settings${CL}"
}
function advanced_settings() {
METHOD="advanced"
vm_prompt_vmid "${VMID:-$(get_valid_nextid)}"
vm_prompt_machine_type "q35"
vm_prompt_disk_size "16G" "Set Disk Size in GiB (e.g., 16, 32)"
vm_prompt_disk_cache "none"
vm_prompt_hostname "truenas"
vm_prompt_cpu_model "host"
vm_prompt_cpu_cores "2"
vm_prompt_ram "8192"
vm_prompt_bridge "vmbr0"
vm_prompt_mac "$GEN_MAC"
vm_prompt_vlan
vm_prompt_mtu
vm_prompt_verbose "no"
DISK_SIZE="16"
HN="truenas"
CORE_COUNT="2"
RAM_SIZE="8192"
BRG="vmbr0"
if vm_dialog yesno "IMPORT ONBOARD DISKS" --defaultno "Would you like to import onboard disks?" 10 58; then
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
ISOARRAY=()
mapfile -t ALL_ISOS < <(truenas_iso_lookup | sort -V)
ISO_COUNT=${#ALL_ISOS[@]}
if [ $ISO_COUNT -eq 0 ]; then
echo "No ISOs found."
exit 115
fi
# Identify the index of the last stable release
LAST_STABLE_INDEX=-1
for i in "${!ALL_ISOS[@]}"; do
if [[ ! "${ALL_ISOS[$i]}" =~ (BETA|RC) ]]; then
LAST_STABLE_INDEX=$i
fi
done
# Build the whiptail array
for i in "${!ALL_ISOS[@]}"; do
ISOPATH="${ALL_ISOS[$i]}"
FILENAME=$(basename "$ISOPATH")
# Select ON if it's the last stable found, OR fallback to last item if no stable exists
if [[ "$i" -eq "$LAST_STABLE_INDEX" ]]; then
ISOARRAY+=("$ISOPATH" "$FILENAME" "ON")
elif [[ "$LAST_STABLE_INDEX" -eq -1 && "$i" -eq "$((ISO_COUNT - 1))" ]]; then
# Fallback: if somehow no stable is found, select the very last item
ISOARRAY+=("$ISOPATH" "$FILENAME" "ON")
else
ISOARRAY+=("$ISOPATH" "$FILENAME" "OFF")
fi
done
if SELECTED_ISO=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT ISO TO INSTALL" --notags --radiolist "\nSelect version (BETA/RC/Latest stable):" 20 58 12 "${ISOARRAY[@]}" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
echo -e "${ISO}${BOLD}${DGN}ISO Chosen: ${BGN}$(basename "$SELECTED_ISO")${CL}"
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
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).${CL}"
exit-script
fi
else
exit-script
fi
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 "$HN" --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VM_NAME ]; then
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
HN=$(echo "${VM_NAME,,}" | tr -cs 'a-z0-9-' '-' | sed 's/^-//;s/-$//')
if [ "$HN" != "${VM_NAME,,}" ]; then
whiptail --backtitle "Proxmox VE Helper Scripts" --title "HOSTNAME ADJUSTED" --msgbox "Invalid characters detected. Hostname has been adjusted to:\n\n $HN" 10 58
fi
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
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" OFF \
"Host" "Use host CPU features (faster, no migration)" ON \
3>&1 1>&2 2>&3); then
case "$CPU_TYPE1" in
Host)
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
CPU_TYPE="host"
;;
*)
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
CPU_TYPE=""
;;
esac
else
exit-script
fi
while true; do
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 "$CORE_COUNT" --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$CORE_COUNT" ]; then CORE_COUNT="2"; fi
if [[ "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "CPU Cores must be a positive integer (e.g., 2)." 8 58
else
exit-script
fi
done
while true; do
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 "$RAM_SIZE" --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$RAM_SIZE" ]; then RAM_SIZE="8192"; fi
if [[ "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "RAM Size must be a positive integer in MiB (e.g., 8192)." 8 58
else
exit-script
fi
done
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 "$BRG" --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
exit-script
fi
while true; do
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}"
break
fi
if [[ "$MAC1" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then
MAC="$MAC1"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "Invalid MAC address format. Use XX:XX:XX:XX:XX:XX (e.g., AA:BB:CC:DD:EE:FF)." 8 58
else
exit-script
fi
done
while true; do
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}"
break
fi
if [[ "$VLAN1" =~ ^[0-9]+$ ]] && [ "$VLAN1" -ge 1 ] && [ "$VLAN1" -le 4094 ]; then
VLAN=",tag=$VLAN1"
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "VLAN must be a number between 1 and 4094, or leave blank for default." 8 58
else
exit-script
fi
done
while true; do
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}"
break
fi
if [[ "$MTU1" =~ ^[0-9]+$ ]] && [ "$MTU1" -ge 576 ] && [ "$MTU1" -le 65520 ]; then
MTU=",mtu=$MTU1"
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "MTU Size must be a number between 576 and 65520, or leave blank for default." 8 58
else
exit-script
fi
done
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "IMPORT ONBOARD DISKS" --yesno "Would you like to import onboard disks?" 10 58); then
echo -e "${DISK}${BOLD}${DGN}Import onboard disks: ${BGN}yes${CL}"
IMPORT_DISKS="yes"
else
echo -e "${DISK}${BOLD}${DGN}Import onboard disks: ${BGN}no${CL}"
IMPORT_DISKS="no"
fi
echo -e "${DISK}${BOLD}${DGN}Import onboard disks: ${BGN}${IMPORT_DISKS}${CL}"
vm_prompt_start_vm "yes"
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 vm_confirm_advanced_settings "Ready to create a TrueNAS VM?"; then
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a TrueNAS VM?" --no-button Do-Over 10 58); then
echo -e "${CREATING}${BOLD}${DGN}Creating a TrueNAS VM using the above advanced settings${CL}"
else
header_info
@@ -132,11 +501,54 @@ function advanced_settings() {
fi
}
vm_preflight
vm_start_script "Use Default Settings?" 10 58
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
}
check_root
arch_check
pve_check
ssh_check
start_script
post_to_api_vm
vm_select_storage "$HN"
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")
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
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
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
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
if [ -z "${SELECTED_ISO:-}" ]; then
SELECTED_ISO=$(truenas_iso_lookup | grep -vE 'RC|BETA' | sort -V | tail -n 1)
@@ -152,17 +564,21 @@ ISO_NAME=$(basename "$FULL_URL")
CACHE_DIR="/var/lib/vz/template/iso"
CACHE_FILE="$CACHE_DIR/$ISO_NAME"
msg_info "Retrieving the ISO for the TrueNAS Disk Image"
MIN_ISO_BYTES=$((500 * 1024 * 1024))
vm_fetch_image "$FULL_URL" "$CACHE_FILE" --cache --min-bytes "$MIN_ISO_BYTES" || exit 115
if [[ ! -s "$CACHE_FILE" ]]; then
msg_info "Retrieving the ISO for the TrueNAS Disk Image"
curl -f#SL -o "$CACHE_FILE" "$FULL_URL"
msg_ok "Downloaded ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
else
msg_ok "Using cached image ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
fi
set -o pipefail
msg_info "Creating TrueNAS VM shell"
qm create "$VMID"${MACHINE} -bios ovmf -agent enabled=1 -tablet 0 -localtime 1${CPU_TYPE} \
qm create "$VMID" -machine q35 -bios ovmf -agent enabled=1 -tablet 0 -localtime 1 -cpu "$CPU_TYPE" \
-cores "$CORE_COUNT" -memory "$RAM_SIZE" -balloon 0 -name "$HN" -tags community-script \
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 \
-efidisk0 $STORAGE:1,efitype=4m,pre-enrolled-keys=0 -sata0 $STORAGE:$DISK_SIZE,ssd=1 \
-scsihw virtio-scsi-single -cdrom local:iso/$ISO_NAME -boot order='sata0;ide2' -vga virtio >/dev/null
-scsihw virtio-scsi-single -cdrom local:iso/$ISO_NAME -vga virtio >/dev/null
msg_ok "Created VM shell"
if [ "$IMPORT_DISKS" == "yes" ]; then
@@ -178,9 +594,7 @@ if [ "$IMPORT_DISKS" == "yes" ]; then
DISKARRAY+=("$LSOUTPUT" "$TRUNCATED" "OFF")
done < <(ls /dev/disk/by-id | grep -E '^ata-|^nvme-|^usb-' | grep -v 'part')
vm_dialog checklist "SELECT DISKS TO IMPORT" --notags --cancel-button "Exit Script" \
"\nSelect disk IDs to import. (Use Spacebar to select)\n" 20 58 10 "${DISKARRAY[@]}" || exit
SELECTIONS=$(echo "$VM_DIALOG_RESULT" | tr -d '"')
SELECTIONS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT DISKS TO IMPORT" --checklist "\nSelect disk IDs to import. (Use Spacebar to select)\n" --notags --cancel-button "Exit Script" 20 58 10 "${DISKARRAY[@]}" 3>&1 1>&2 2>&3 | tr -d '"') || exit
for SELECTION in $SELECTIONS; do
((++SCSI_NR))
@@ -193,14 +607,44 @@ if [ "$IMPORT_DISKS" == "yes" ]; then
msg_ok "Disks imported successfully"
fi
set_description
DESCRIPTION=$(
cat <<EOF
<div align='center'>
<a href='https://community-scripts.org' target='_blank' rel='noopener noreferrer'>
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
</a>
<h2 style='font-size: 24px; margin: 20px 0;'>TrueNAS Community Edition</h2>
<p style='margin: 16px 0;'>
<a href='https://ko-fi.com/community_scripts' target='_blank' rel='noopener noreferrer'>
<img src='https://img.shields.io/badge/&#x2615;-Buy us a coffee-blue' alt='spend Coffee' />
</a>
</p>
<span style='margin: 0 10px;'>
<i class="fa fa-github fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-comments fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-exclamation-circle fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
</span>
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
sleep 3
msg_ok "Created a TrueNAS VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
msg_info "Starting TrueNAS VM"
$STD qm start $VMID
qm start $VMID
msg_ok "Started TrueNAS VM"
fi