Compare commits

..

2 Commits

Author SHA1 Message Date
e1825a25e6 Update 2fauth-install.sh 2025-12-16 10:09:43 +01:00
a379c663d9 fix(2fauth): use default PHP version instead of hardcoded 8.3
- Remove hardcoded PHP_VERSION=8.3, let setup_php use default (8.4)
- Remove invalid modules 'session' and 'openssl' (part of php-common)
- Remove duplicate 'cli' module (already in DEFAULT_MODULES)
- Make nginx fastcgi_pass use dynamic PHP_VERSION variable

Fixes installation on Debian 13 (Trixie) which ships PHP 8.4.
2025-12-16 10:06:06 +01:00
51 changed files with 381 additions and 741 deletions

View File

@ -12,30 +12,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
## 2025-12-16 ## 2025-12-16
### 🆕 New Scripts
- [REFACTOR]: NetVisor => Scanopy [@vhsdream](https://github.com/vhsdream) ([#10011](https://github.com/community-scripts/ProxmoxVE/pull/10011))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- zabbix: fix repo url after change [@MickLesk](https://github.com/MickLesk) ([#10042](https://github.com/community-scripts/ProxmoxVE/pull/10042))
- Fix: mariadb repo in update_scripts [@MickLesk](https://github.com/MickLesk) ([#10034](https://github.com/community-scripts/ProxmoxVE/pull/10034))
- 2fauth: update PHP version from 8.3 to 8.4 in update_script [@MickLesk](https://github.com/MickLesk) ([#10035](https://github.com/community-scripts/ProxmoxVE/pull/10035))
- pdm: add rsyslog to fix /dev/log Connection refused errors [@MickLesk](https://github.com/MickLesk) ([#10018](https://github.com/community-scripts/ProxmoxVE/pull/10018))
- 2fauth: bump to php8.4 [@MickLesk](https://github.com/MickLesk) ([#10019](https://github.com/community-scripts/ProxmoxVE/pull/10019))
- Miniflux: use correct systemctl to check service instead of file path [@MickLesk](https://github.com/MickLesk) ([#10024](https://github.com/community-scripts/ProxmoxVE/pull/10024))
- PhotoPrism: export env variables for CLI tools [@MickLesk](https://github.com/MickLesk) ([#10023](https://github.com/community-scripts/ProxmoxVE/pull/10023))
### 💾 Core
- #### ✨ New Features
- core: IP-Range-Scan Support (app.vars / default.vars) [@MickLesk](https://github.com/MickLesk) ([#10038](https://github.com/community-scripts/ProxmoxVE/pull/10038))
- tools.func: add optional enabled parameter to setup_deb822_repo [@MickLesk](https://github.com/MickLesk) ([#10017](https://github.com/community-scripts/ProxmoxVE/pull/10017))
- core: map Etc/* timezones to 'host' for pct compatibility [@MickLesk](https://github.com/MickLesk) ([#10020](https://github.com/community-scripts/ProxmoxVE/pull/10020))
## 2025-12-15 ## 2025-12-15
### 🆕 New Scripts ### 🆕 New Scripts

View File

@ -28,21 +28,20 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "2fauth" "Bubka/2FAuth"; then if check_for_gh_release "2fauth" "Bubka/2FAuth"; then
$STD apt update $STD apt update
$STD apt -y upgrade $STD apt -y upgrade
msg_info "Creating Backup" msg_info "Creating Backup"
mv "/opt/2fauth" "/opt/2fauth-backup" mv "/opt/2fauth" "/opt/2fauth-backup"
if ! dpkg -l | grep -q 'php8.4'; then if ! dpkg -l | grep -q 'php8.3'; then
cp /etc/nginx/conf.d/2fauth.conf /etc/nginx/conf.d/2fauth.conf.bak cp /etc/nginx/conf.d/2fauth.conf /etc/nginx/conf.d/2fauth.conf.bak
fi fi
msg_ok "Backup Created" msg_ok "Backup Created"
if ! dpkg -l | grep -q 'php8.4'; then if ! dpkg -l | grep -q 'php8.3'; then
PHP_VERSION="8.4" PHP_MODULE="common,ctype,fileinfo,mysql,cli,tokenizer,dom,redis,session,openssl" PHP_FPM="YES" setup_php PHP_VERSION="8.3" PHP_MODULE="common,ctype,fileinfo,mysql,cli,tokenizer,dom,redis,session,openssl" PHP_FPM="YES" setup_php
sed -i 's/php8\.[0-9]/php8.4/g' /etc/nginx/conf.d/2fauth.conf sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/2fauth.conf
fi fi
fetch_and_deploy_gh_release "2fauth" "Bubka/2FAuth" fetch_and_deploy_gh_release "2fauth" "Bubka/2FAuth"
setup_composer setup_composer

View File

@ -20,16 +20,15 @@ color
catch_errors catch_errors
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /opt/apache-guacamole ]]; then if [[ ! -d /opt/apache-guacamole ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
exit exit
fi
setup_mariadb
msg_error "Currently we don't provide an update function for this ${APP}."
exit
} }
start start

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "booklore" "booklore-app/BookLore"; then if check_for_gh_release "booklore" "booklore-app/BookLore"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop booklore systemctl stop booklore

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "bookstack" "BookStackApp/BookStack"; then if check_for_gh_release "bookstack" "BookStackApp/BookStack"; then
msg_info "Stopping Apache2" msg_info "Stopping Apache2"
systemctl stop apache2 systemctl stop apache2

View File

@ -20,16 +20,15 @@ color
catch_errors catch_errors
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /usr/share/dolibarr ]]; then if [[ ! -d /usr/share/dolibarr ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "To update ${APP}, use the applications web interface."
exit exit
fi
setup_mariadb
msg_error "To update ${APP}, use the applications web interface."
exit
} }
start start
@ -39,4 +38,4 @@ description
msg_ok "Completed Successfully!\n" msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}" echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/dolibarr/install${CL}" echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/dolibarr/install${CL}"

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if ! grep -Fq "root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then if ! grep -Fq "root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then
echo "0 0 * * * root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab echo "0 0 * * * root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab

View File

@ -28,7 +28,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then
systemctl stop apache2 systemctl stop apache2
cp /opt/firefly/.env /opt/.env cp /opt/firefly/.env /opt/.env

View File

@ -23,7 +23,6 @@ function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
setup_mariadb
NODE_VERSION="22" setup_nodejs NODE_VERSION="22" setup_nodejs

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
RELEASE=$(curl -fsSL https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') RELEASE=$(curl -fsSL https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_error "Currently we don't provide an update function for this ${APP}." msg_error "Currently we don't provide an update function for this ${APP}."

View File

@ -1,6 +1,6 @@
_____ _ __ __ _ ___
/ ___/_________ _____ ____ ____ __ __ / | / /__ / /| | / (_)________ _____
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / / / |/ / _ \/ __/ | / / / ___/ __ \/ ___/
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ / / /| / __/ /_ | |/ / (__ ) /_/ / /
/____/\___/\__,_/_/ /_/\____/ .___/\__, / /_/ |_/\___/\__/ |___/_/____/\____/_/
/_/ /____/

View File

@ -1,6 +0,0 @@
_____
/ ___/_________ _____ ____ ____ __ __
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / /
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ /
/____/\___/\__,_/_/ /_/\____/ .___/\__, /
/_/ /____/

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "hortusfox" "danielbrendel/hortusfox-web"; then if check_for_gh_release "hortusfox" "danielbrendel/hortusfox-web"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop apache2 systemctl stop apache2

View File

@ -28,7 +28,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "invoiceninja" "invoiceninja/invoiceninja"; then if check_for_gh_release "invoiceninja" "invoiceninja/invoiceninja"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop supervisor nginx php8.4-fpm systemctl stop supervisor nginx php8.4-fpm

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 1 exit 1
fi fi
setup_mariadb
msg_info "Updating LXC" msg_info "Updating LXC"
$STD apt update $STD apt update

View File

@ -30,12 +30,11 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" setup_php PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" setup_php
setup_composer setup_composer
if check_for_gh_release "kimai" "kimai/kimai"; then if check_for_gh_release "kimai" "kimai/kimai"; then
BACKUP_DIR="/opt/kimai_backup" BACKUP_DIR="/opt/kimai_backup"
msg_info "Stopping Apache2" msg_info "Stopping Apache2"

View File

@ -28,7 +28,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "leantime" "Leantime/leantime"; then if check_for_gh_release "leantime" "Leantime/leantime"; then
msg_info "Creating Backup" msg_info "Creating Backup"
mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql" mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql"

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
msg_info "Updating LibreNMS" msg_info "Updating LibreNMS"
su librenms su librenms
cd /opt/librenms cd /opt/librenms

View File

@ -20,17 +20,16 @@ color
catch_errors catch_errors
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /opt/limesurvey ]]; then if [[ ! -d /opt/limesurvey ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
msg_warn "Application is updated via Web Interface" msg_warn "Application is updated via Web Interface"
exit exit
} }
start start

View File

@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "mmdl" "intri-in/manage-my-damn-life-nextjs"; then if check_for_gh_release "mmdl" "intri-in/manage-my-damn-life-nextjs"; then
msg_info "Stopping service" msg_info "Stopping service"
systemctl stop mmdl systemctl stop mmdl

View File

@ -20,19 +20,18 @@ color
catch_errors catch_errors
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /etc/mysql/mariadb.conf.d ]]; then if [[ ! -d /etc/mysql/mariadb.conf.d ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ${APP} LXC"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated successfully!"
exit exit
fi
setup_mariadb
msg_info "Updating ${APP} LXC"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated successfully!"
exit
} }
start start

View File

@ -23,7 +23,7 @@ function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if ! systemctl -q is-enabled miniflux 2>/dev/null; then if [[ ! -f /etc/systemd/system/miniflux.service ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
@ -34,7 +34,7 @@ function update_script() {
msg_ok "Service Stopped" msg_ok "Service Stopped"
fetch_and_deploy_gh_release "miniflux" "miniflux/v2" "binary" "latest" fetch_and_deploy_gh_release "miniflux" "miniflux/v2" "binary" "latest"
msg_info "Updating Miniflux" msg_info "Updating Miniflux"
$STD miniflux -migrate -config-file /etc/miniflux.conf $STD miniflux -migrate -config-file /etc/miniflux.conf
msg_ok "Updated Miniflux" msg_ok "Updated Miniflux"

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs

View File

@ -3,9 +3,9 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Copyright (c) 2021-2025 community-scripts ORG # Copyright (c) 2021-2025 community-scripts ORG
# Author: vhsdream # Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/scanopy/scanopy # Source: https://github.com/netvisor-io/netvisor
APP="Scanopy" APP="NetVisor"
var_tags="${var_tags:-analytics}" var_tags="${var_tags:-analytics}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-3072}" var_ram="${var_ram:-3072}"
@ -29,74 +29,71 @@ function update_script() {
exit exit
fi fi
msg_info "Stopping services" if check_for_gh_release "netvisor" "netvisor-io/netvisor"; then
systemctl -q disable --now netvisor-daemon netvisor-server msg_info "Stopping services"
msg_ok "Stopped services" systemctl stop netvisor-daemon netvisor-server
msg_ok "Stopped services"
NODE_VERSION="24" setup_nodejs msg_info "Backing up configurations"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy" cp /opt/netvisor/.env /opt/netvisor.env.bak
if [[ -f /opt/netvisor/oidc.toml ]]; then
cp /opt/netvisor/oidc.toml /opt/netvisor.oidc.toml
fi
msg_ok "Backed up configurations"
if ! dpkg -l | grep -q "pkg-config"; then CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "netvisor-io/netvisor" "tarball" "latest" "/opt/netvisor"
$STD apt install -y pkg-config
if ! dpkg -l | grep -q "pkg-config"; then
$STD apt install -y pkg-config
fi
if ! dpkg -l | grep -q "libssl-dev"; then
$STD apt install -y libssl-dev
fi
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
mv /opt/netvisor.env.bak /opt/netvisor/.env
if [[ -f /opt/netvisor.oidc.toml ]]; then
mv /opt/netvisor.oidc.toml /opt/netvisor/oidc.toml
fi
LOCAL_IP="$(hostname -I | awk '{print $1}')"
if ! grep -q "PUBLIC_URL" /opt/netvisor/.env; then
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/netvisor/.env
fi
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/netvisor/.env
msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=""
cd /opt/netvisor/ui
$STD npm ci --no-fund --no-audit
$STD npm run build
msg_ok "Created frontend UI"
msg_info "Building Netvisor-server (patience)"
cd /opt/netvisor/backend
$STD cargo build --release --bin server
mv ./target/release/server /usr/bin/netvisor-server
msg_ok "Built Netvisor-server"
msg_info "Building Netvisor-daemon"
$STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/netvisor-daemon
msg_ok "Built Netvisor-daemon"
sed -i -e 's|-target|-url|' \
-e 's| --server-port |:|' \
/etc/systemd/system/netvisor-daemon.service
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
if ! grep -q "WorkingD" /etc/systemd/system/netvisor-server.service; then
sed -i '\|simple$|a\WorkingDirectory=/opt/netvisor/backend' /etc/systemd/system/netvisor-server.service
fi
systemctl daemon-reload
msg_info "Starting services"
systemctl start netvisor-server netvisor-daemon
msg_ok "Updated successfully!"
fi fi
if ! dpkg -l | grep -q "libssl-dev"; then
$STD apt install -y libssl-dev
fi
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
mv /opt/netvisor/.env /opt/scanopy/.env
if [[ -f /opt/netvisor/oidc.toml ]]; then
mv /opt/netvisor/oidc.toml /opt/scanopy/oidc.toml
fi
LOCAL_IP="$(hostname -I | awk '{print $1}')"
if ! grep -q "PUBLIC_URL" /opt/scanopy/.env; then
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/scanopy/.env
fi
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/scanopy/.env
sed -i 's/NETVISOR/SCANOPY/g; s|netvisor/|scanopy/|' /opt/scanopy/.env
msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=""
cd /opt/scanopy/ui
$STD npm ci --no-fund --no-audit
$STD npm run build
msg_ok "Created frontend UI"
msg_info "Building Scanopy-server (patience)"
cd /opt/scanopy/backend
$STD cargo build --release --bin server
mv ./target/release/server /usr/bin/scanopy-server
msg_ok "Built Scanopy-server"
msg_info "Building Scanopy-daemon"
$STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/scanopy-daemon
msg_ok "Built Scanopy-daemon"
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
sed -i -e 's|-target|-url|' \
-e 's| --server-port |:|' \
-e 's/NetVisor/Scanopy/' \
-e 's/netvisor/scanopy/' \
/etc/systemd/system/netvisor-daemon.service
mv /etc/systemd/system/netvisor-daemon.service /etc/systemd/system/scanopy-daemon.service
sed -i -e 's/NetVisor/Scanopy/' \
-e 's/netvisor/scanopy/g' \
/etc/systemd/system/netvisor-server.service
mv /etc/systemd/system/netvisor-server.service /etc/systemd/system/scanopy-server.service
systemctl daemon-reload
msg_info "Starting services"
systemctl -q enable --now scanopy-server scanopy-daemon
msg_ok "Updated successfully!"
sed -i 's/netvisor/scanopy/' /usr/bin/update
mv ~/NetVisor.creds ~/scanopy.creds
rm ~/.netvisor
rm -rf /opt/netvisor
exit exit
} }

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
msg_info "Updating $APP LXC" msg_info "Updating $APP LXC"
$STD apt update $STD apt update
$STD apt upgrade -y $STD apt upgrade -y

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2) CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
if [[ "$CURRENT_PHP" != "8.3" ]]; then if [[ "$CURRENT_PHP" != "8.3" ]]; then

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2) CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
if [[ "$CURRENT_PHP" != "8.4" ]]; then if [[ "$CURRENT_PHP" != "8.4" ]]; then

View File

@ -31,13 +31,6 @@ function update_script() {
msg_info "Stopping PhotoPrism" msg_info "Stopping PhotoPrism"
systemctl stop photoprism systemctl stop photoprism
msg_ok "Stopped PhotoPrism" msg_ok "Stopped PhotoPrism"
if ! grep -q "photoprism/config/.env" ~/.bashrc 2>/dev/null; then
msg_info "Adding environment export for CLI tools"
echo '# Load PhotoPrism environment variables for CLI tools' >>~/.bashrc
echo 'export $(grep -v "^#" /opt/photoprism/config/.env | xargs)' >>~/.bashrc
msg_ok "Added environment export"
fi
fetch_and_deploy_gh_release "photoprism" "photoprism/photoprism" "prebuild" "latest" "/opt/photoprism" "*linux-amd64.tar.gz" fetch_and_deploy_gh_release "photoprism" "photoprism/photoprism" "prebuild" "latest" "/opt/photoprism" "*linux-amd64.tar.gz"

View File

@ -27,7 +27,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "phpipam" "phpipam/phpipam"; then if check_for_gh_release "phpipam" "phpipam/phpipam"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop apache2 systemctl stop apache2

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop plant-it systemctl stop plant-it

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "projectsend" "projectsend/projectsend"; then if check_for_gh_release "projectsend" "projectsend/projectsend"; then
msg_info "Stopping Service" msg_info "Stopping Service"

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2) CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
if [[ "$CURRENT_PHP" != "8.4" ]]; then if [[ "$CURRENT_PHP" != "8.4" ]]; then

View File

@ -1,99 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2025 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/scanopy/scanopy
APP="Scanopy"
var_tags="${var_tags:-analytics}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-3072}"
var_disk="${var_disk:-6}"
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/scanopy ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "scanopy" "scanopy-io/scanopy"; then
msg_info "Stopping services"
systemctl stop scanopy-daemon scanopy-server
msg_ok "Stopped services"
msg_info "Backing up configurations"
cp /opt/scanopy/.env /opt/scanopy.env.bak
if [[ -f /opt/scanopy/oidc.toml ]]; then
cp /opt/scanopy/oidc.toml /opt/scanopy.oidc.toml
fi
msg_ok "Backed up configurations"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
if ! dpkg -l | grep -q "pkg-config"; then
$STD apt install -y pkg-config
fi
if ! dpkg -l | grep -q "libssl-dev"; then
$STD apt install -y libssl-dev
fi
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
mv /opt/scanopy.env.bak /opt/scanopy/.env
if [[ -f /opt/scanopy.oidc.toml ]]; then
mv /opt/scanopy.oidc.toml /opt/scanopy/oidc.toml
fi
LOCAL_IP="$(hostname -I | awk '{print $1}')"
if ! grep -q "PUBLIC_URL" /opt/scanopy/.env; then
sed -i "\|_PATH=|a\scanopy_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/scanopy/.env
fi
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/scanopy/.env
msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=""
cd /opt/scanopy/ui
$STD npm ci --no-fund --no-audit
$STD npm run build
msg_ok "Created frontend UI"
msg_info "Building scanopy-server (patience)"
cd /opt/scanopy/backend
$STD cargo build --release --bin server
mv ./target/release/server /usr/bin/scanopy-server
msg_ok "Built scanopy-server"
msg_info "Building scanopy-daemon"
$STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/scanopy-daemon
msg_ok "Built scanopy-daemon"
msg_info "Starting services"
systemctl start scanopy-server scanopy-daemon
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}:60072${CL}"
echo -e "${INFO}${YW} Then create your account, and run the 'configure_daemon.sh' script to setup the daemon.${CL}"

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
msg_info "Updating Shinobi" msg_info "Updating Shinobi"
cd /opt/Shinobi cd /opt/Shinobi
$STD sh UPDATE.sh $STD sh UPDATE.sh

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then
sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf
fi fi

View File

@ -28,7 +28,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "wallabag" "wallabag/wallabag"; then if check_for_gh_release "wallabag" "wallabag/wallabag"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop nginx php8.3-fpm systemctl stop nginx php8.3-fpm

View File

@ -27,7 +27,7 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
if check_for_gh_release "wavelog" "wavelog/wavelog"; then if check_for_gh_release "wavelog" "wavelog/wavelog"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop apache2 systemctl stop apache2

View File

@ -27,7 +27,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
setup_mariadb
msg_error "Wordpress should be updated via the user interface." msg_error "Wordpress should be updated via the user interface."
exit exit
} }

View File

@ -67,7 +67,7 @@ function update_script() {
rm -Rf /etc/apt/sources.list.d/zabbix.list rm -Rf /etc/apt/sources.list.d/zabbix.list
cd /tmp cd /tmp
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb" ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
$STD dpkg -i zabbix-release_latest+debian13_all.deb $STD dpkg -i zabbix-release_latest+debian13_all.deb
rm -rf /tmp/zabbix-release_latest+debian13_all.deb rm -rf /tmp/zabbix-release_latest+debian13_all.deb

View File

@ -434,24 +434,12 @@ var_unprivileged=1 # 0=privileged, 1=unprivileged
#### Network #### Network
```bash ```bash
var_brg=vmbr0 # Bridge interface var_brg=vmbr0 # Bridge interface
var_net=dhcp # dhcp, static IP/CIDR, or IP range (see below) var_net=veth # Network driver
var_gateway=192.168.1.1 # Default gateway (required for static IP) var_gateway=192.168.1.1 # Default gateway
var_mtu=1500 # MTU size var_mtu=1500 # MTU size
var_vlan=100 # VLAN ID var_vlan=100 # VLAN ID
``` ```
#### IP Range Scanning
You can specify an IP range instead of a static IP. The system will ping each IP in the range and automatically assign the first free IP:
```bash
# Format: START_IP/CIDR-END_IP/CIDR
var_net=192.168.1.100/24-192.168.1.200/24
var_gateway=192.168.1.1
```
This is useful for automated deployments where you want static IPs but don't want to track which IPs are already in use.
#### System #### System
```bash ```bash
var_hostname=pihole # Container name var_hostname=pihole # Container name

View File

@ -122,31 +122,6 @@ var_verbose=no \
echo "✓ Container deployed successfully" echo "✓ Container deployed successfully"
``` ```
### Using IP Range Scan for Automatic IP Assignment
Instead of manually specifying static IPs, you can define an IP range. The system will automatically ping each IP and assign the first free one:
```bash
#!/bin/bash
# deploy-with-ip-scan.sh - Auto-assign first free IP from range
var_unprivileged=1 \
var_cpu=4 \
var_ram=4096 \
var_hostname=web-server \
var_net=192.168.1.100/24-192.168.1.150/24 \
var_gateway=192.168.1.1 \
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/debian.sh)"
# The script will:
# 1. Ping 192.168.1.100 - if responds, skip
# 2. Ping 192.168.1.101 - if responds, skip
# 3. Continue until first IP that doesn't respond
# 4. Assign that IP to the container
```
> **Note**: IP range format is `START_IP/CIDR-END_IP/CIDR`. Both sides must include the same CIDR notation.
### Using App Defaults ### Using App Defaults
**Step 1: Create defaults once (interactive)** **Step 1: Create defaults once (interactive)**

View File

@ -1,6 +1,6 @@
{ {
"name": "Scanopy", "name": "NetVisor",
"slug": "scanopy", "slug": "netvisor",
"categories": [ "categories": [
9 9
], ],
@ -9,15 +9,15 @@
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": 60072, "interface_port": 60072,
"documentation": "https://github.com/scanopy/scanopy", "documentation": "https://github.com/netvisor-io/netvisor",
"config_path": "/opt/scanopy/.env, OIDC: /opt/scanopy/oidc.toml", "config_path": "/opt/netvisor/.env, OIDC: /opt/netvisor/oidc.toml",
"website": "https://scanopy.net", "website": "https://netvisor.io",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/scanopy.webp", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/netvisor.png",
"description": "Automatically discover and visually document network infrastructure", "description": "Automatically discover and visually document network infrastructure",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "ct/scanopy.sh", "script": "ct/netvisor.sh",
"resources": { "resources": {
"cpu": 2, "cpu": 2,
"ram": 3072, "ram": 3072,

View File

@ -1,89 +1,4 @@
[ [
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.542",
"date": "2025-12-16T11:28:32Z"
},
{
"name": "zabbix/zabbix",
"version": "7.2.15rc2",
"date": "2025-12-16T10:23:14Z"
},
{
"name": "prometheus/prometheus",
"version": "v3.8.1",
"date": "2025-12-16T09:59:22Z"
},
{
"name": "rcourtman/Pulse",
"version": "v4.36.2",
"date": "2025-12-03T22:46:29Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@1.123.6",
"date": "2025-12-15T14:22:59Z"
},
{
"name": "sabnzbd/sabnzbd",
"version": "4.5.5",
"date": "2025-10-24T11:12:22Z"
},
{
"name": "mattermost/mattermost",
"version": "v11.2.1",
"date": "2025-12-16T07:40:44Z"
},
{
"name": "jupyter/notebook",
"version": "v7.5.1",
"date": "2025-12-16T07:39:08Z"
},
{
"name": "morpheus65535/bazarr",
"version": "v1.5.3",
"date": "2025-09-20T12:12:33Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.24.457",
"date": "2025-12-16T05:57:07Z"
},
{
"name": "firefly-iii/firefly-iii",
"version": "v6.4.14",
"date": "2025-12-16T05:42:34Z"
},
{
"name": "goauthentik/authentik",
"version": "version/2025.10.2",
"date": "2025-11-19T15:08:41Z"
},
{
"name": "ollama/ollama",
"version": "v0.13.4-rc2",
"date": "2025-12-16T02:57:20Z"
},
{
"name": "jeedom/core",
"version": "4.5",
"date": "2025-12-16T00:27:09Z"
},
{
"name": "steveiliop56/tinyauth",
"version": "v4.1.0",
"date": "2025-11-23T12:13:34Z"
},
{
"name": "Stirling-Tools/Stirling-PDF",
"version": "v2.1.4",
"date": "2025-12-16T00:02:18Z"
},
{
"name": "esphome/esphome",
"version": "2025.11.5",
"date": "2025-12-09T17:54:33Z"
},
{ {
"name": "scanopy/scanopy", "name": "scanopy/scanopy",
"version": "v0.12.1", "version": "v0.12.1",
@ -94,6 +9,11 @@
"version": "v2.16.46", "version": "v2.16.46",
"date": "2025-12-15T22:07:08Z" "date": "2025-12-15T22:07:08Z"
}, },
{
"name": "mattermost/mattermost",
"version": "mattermost-redux@11.2.0",
"date": "2025-12-15T20:37:15Z"
},
{ {
"name": "metabase/metabase", "name": "metabase/metabase",
"version": "v0.57.x", "version": "v0.57.x",
@ -114,11 +34,6 @@
"version": "v4.1.0", "version": "v4.1.0",
"date": "2025-12-15T18:53:25Z" "date": "2025-12-15T18:53:25Z"
}, },
{
"name": "keycloak/keycloak",
"version": "26.4.7",
"date": "2025-12-01T08:14:11Z"
},
{ {
"name": "rabbitmq/rabbitmq-server", "name": "rabbitmq/rabbitmq-server",
"version": "v4.2.2", "version": "v4.2.2",
@ -134,6 +49,16 @@
"version": "v0.30.0", "version": "v0.30.0",
"date": "2025-12-15T17:23:59Z" "date": "2025-12-15T17:23:59Z"
}, },
{
"name": "n8n-io/n8n",
"version": "n8n@1.123.6",
"date": "2025-12-15T14:22:59Z"
},
{
"name": "rcourtman/Pulse",
"version": "v4.36.2",
"date": "2025-12-03T22:46:29Z"
},
{ {
"name": "danielbrendel/hortusfox-web", "name": "danielbrendel/hortusfox-web",
"version": "v5.6", "version": "v5.6",
@ -144,6 +69,11 @@
"version": "25.12.0", "version": "25.12.0",
"date": "2025-12-15T14:06:00Z" "date": "2025-12-15T14:06:00Z"
}, },
{
"name": "firefly-iii/firefly-iii",
"version": "v6.4.11",
"date": "2025-12-15T08:01:35Z"
},
{ {
"name": "tailscale/tailscale", "name": "tailscale/tailscale",
"version": "v1.92.2", "version": "v1.92.2",
@ -189,11 +119,36 @@
"version": "v6.0.4.10291", "version": "v6.0.4.10291",
"date": "2025-11-16T22:39:01Z" "date": "2025-11-16T22:39:01Z"
}, },
{
"name": "morpheus65535/bazarr",
"version": "v1.5.3",
"date": "2025-09-20T12:12:33Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.24.454",
"date": "2025-12-15T05:54:27Z"
},
{ {
"name": "jellyfin/jellyfin", "name": "jellyfin/jellyfin",
"version": "v10.11.5", "version": "v10.11.5",
"date": "2025-12-15T02:44:19Z" "date": "2025-12-15T02:44:19Z"
}, },
{
"name": "steveiliop56/tinyauth",
"version": "v4.1.0",
"date": "2025-11-23T12:13:34Z"
},
{
"name": "jeedom/core",
"version": "4.5",
"date": "2025-12-15T00:27:03Z"
},
{
"name": "esphome/esphome",
"version": "2025.11.5",
"date": "2025-12-09T17:54:33Z"
},
{ {
"name": "9001/copyparty", "name": "9001/copyparty",
"version": "v1.19.22", "version": "v1.19.22",
@ -329,6 +284,11 @@
"version": "v0.88.0", "version": "v0.88.0",
"date": "2025-12-13T09:36:24Z" "date": "2025-12-13T09:36:24Z"
}, },
{
"name": "ollama/ollama",
"version": "v0.13.4-rc0",
"date": "2025-12-13T00:29:01Z"
},
{ {
"name": "Dokploy/dokploy", "name": "Dokploy/dokploy",
"version": "v0.26.2", "version": "v0.26.2",
@ -379,6 +339,11 @@
"version": "v1.14.1", "version": "v1.14.1",
"date": "2025-12-12T17:37:58Z" "date": "2025-12-12T17:37:58Z"
}, },
{
"name": "keycloak/keycloak",
"version": "26.4.7",
"date": "2025-12-01T08:14:11Z"
},
{ {
"name": "node-red/node-red", "name": "node-red/node-red",
"version": "4.1.2", "version": "4.1.2",
@ -454,6 +419,16 @@
"version": "v1.30.22", "version": "v1.30.22",
"date": "2025-12-11T18:02:06Z" "date": "2025-12-11T18:02:06Z"
}, },
{
"name": "Stirling-Tools/Stirling-PDF",
"version": "v2.1.3",
"date": "2025-12-11T13:31:56Z"
},
{
"name": "zabbix/zabbix",
"version": "7.4.6rc1",
"date": "2025-12-11T12:01:51Z"
},
{ {
"name": "pommee/goaway", "name": "pommee/goaway",
"version": "v0.62.24", "version": "v0.62.24",
@ -479,6 +454,11 @@
"version": "v1.8.0", "version": "v1.8.0",
"date": "2025-12-10T16:44:33Z" "date": "2025-12-10T16:44:33Z"
}, },
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.541",
"date": "2025-12-10T15:57:13Z"
},
{ {
"name": "rclone/rclone", "name": "rclone/rclone",
"version": "v1.72.1", "version": "v1.72.1",
@ -579,6 +559,11 @@
"version": "preview-test-fix-subscriptions", "version": "preview-test-fix-subscriptions",
"date": "2025-12-08T23:15:30Z" "date": "2025-12-08T23:15:30Z"
}, },
{
"name": "sabnzbd/sabnzbd",
"version": "4.5.5",
"date": "2025-10-24T11:12:22Z"
},
{ {
"name": "hansmi/prometheus-paperless-exporter", "name": "hansmi/prometheus-paperless-exporter",
"version": "v0.0.9", "version": "v0.0.9",
@ -779,6 +764,11 @@
"version": "v5.0.0", "version": "v5.0.0",
"date": "2025-12-02T10:33:31Z" "date": "2025-12-02T10:33:31Z"
}, },
{
"name": "prometheus/prometheus",
"version": "v3.8.0",
"date": "2025-12-02T10:11:05Z"
},
{ {
"name": "neo4j/neo4j", "name": "neo4j/neo4j",
"version": "5.26.18", "version": "5.26.18",
@ -1054,11 +1044,21 @@
"version": "v12.3.0", "version": "v12.3.0",
"date": "2025-11-19T15:15:43Z" "date": "2025-11-19T15:15:43Z"
}, },
{
"name": "goauthentik/authentik",
"version": "version/2025.10.2",
"date": "2025-11-19T15:08:41Z"
},
{ {
"name": "hivemq/hivemq-community-edition", "name": "hivemq/hivemq-community-edition",
"version": "2025.5", "version": "2025.5",
"date": "2025-11-19T14:48:47Z" "date": "2025-11-19T14:48:47Z"
}, },
{
"name": "jupyter/notebook",
"version": "v7.5.0",
"date": "2025-11-19T08:36:29Z"
},
{ {
"name": "PatchMon/PatchMon", "name": "PatchMon/PatchMon",
"version": "v1.3.6", "version": "v1.3.6",

View File

@ -17,8 +17,7 @@ msg_info "Installing Dependencies"
$STD apt install -y nginx $STD apt install -y nginx
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
PHP_VERSION="8.4" PHP_MODULE="common,ctype,fileinfo,mysql,tokenizer,dom,redis" PHP_VERSION="8.4" PHP_FPM="YES" setup_php
PHP_MODULE="common,ctype,fileinfo,mysql,tokenizer,dom,redis" PHP_FPM="YES" setup_php
setup_composer setup_composer
setup_mariadb setup_mariadb
MARIADB_DB_NAME="2fauth_db" MARIADB_DB_USER="2fauth" setup_mariadb_db MARIADB_DB_NAME="2fauth_db" MARIADB_DB_USER="2fauth" setup_mariadb_db

142
install/netvisor-install.sh Normal file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/netvisor-io/netvisor
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 \
libssl-dev \
pkg-config
msg_ok "Installed Dependencies"
PG_VERSION=17 setup_postgresql
NODE_VERSION="24" setup_nodejs
PG_DB_NAME="netvisor_db" PG_DB_USER="netvisor" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
fetch_and_deploy_gh_release "netvisor" "netvisor-io/netvisor" "tarball" "latest" "/opt/netvisor"
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=""
cd /opt/netvisor/ui
$STD npm ci --no-fund --no-audit
$STD npm run build
msg_ok "Created frontend UI"
msg_info "Building Netvisor-server (patience)"
cd /opt/netvisor/backend
$STD cargo build --release --bin server
mv ./target/release/server /usr/bin/netvisor-server
msg_ok "Built Netvisor-server"
msg_info "Building Netvisor-daemon"
$STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/netvisor-daemon
msg_ok "Built Netvisor-daemon"
msg_info "Configuring server for first-run"
LOCAL_IP="$(hostname -I | awk '{print $1}')"
cat <<EOF >/opt/netvisor/.env
### - SERVER
NETVISOR_DATABASE_URL=postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME
NETVISOR_WEB_EXTERNAL_PATH="/opt/netvisor/ui/build"
NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072
NETVISOR_SERVER_PORT=60072
NETVISOR_LOG_LEVEL=info
NETVISOR_INTEGRATED_DAEMON_URL=http://127.0.0.1:60073
## - uncomment to disable signups
# NETVISOR_DISABLE_REGISTRATION=true
## - uncomment when using TLS
# NETVISOR_USE_SECURE_SESSION_COOKIES=true
## - see https://github.com/imbolc/axum-client-ip?tab=readme-ov-file#configurable-vs-specific-extractors
## - before uncommenting the below
# NETVISOR_CLIENT_IP_SOURCE=
### - SMTP (password reset and notifications - optional)
# NETVISOR_SMTP_RELAY=smtp.gmail.com:587
# NETVISOR_SMTP_USERNAME=your-email@gmail.com
# NETVISOR_SMTP_PASSWORD=your-app-password
# NETVISOR_SMTP_EMAIL=netvisor@yourdomain.tld
### - INTEGRATED DAEMON
NETVISOR_SERVER_URL=http://127.0.0.1:60072
NETVISOR_BIND_ADDRESS=0.0.0.0
NETVISOR_NAME="netvisor-daemon"
NETVISOR_HEARTBEAT_INTERVAL=30
### - see https://github.com/netvisor-io/netvisor/blob/main/docs/CONFIGURATION.md for more options
EOF
cat <<EOF >/etc/systemd/system/netvisor-server.service
[Unit]
Description=NetVisor Network Discovery Server
After=network.target postgresql.service
[Service]
Type=simple
WorkingDirectory=/opt/netvisor/backend
EnvironmentFile=/opt/netvisor/.env
ExecStart=/usr/bin/netvisor-server
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now netvisor-server
# Creating short script to configure netvisor-daemon
cat <<EOF >~/configure_daemon.sh
#!/usr/bin/env bash
echo "Auto-configuring integrated daemon..."
NETWORK_ID="\$(sudo -u postgres psql -1 -t -d "${PG_DB_NAME}" -c 'SELECT id FROM networks;')"
API_KEY="\$(sudo -u postgres psql -1 -t -d "${PG_DB_NAME}" -c 'SELECT key FROM api_keys;')"
cat <<END >/etc/systemd/system/netvisor-daemon.service
[Unit]
Description=NetVisor Network Discovery Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/netvisor-daemon --server-url http://127.0.0.1:60072 --network-id \${NETWORK_ID} --daemon-api-key \${API_KEY} --mode push
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
END
systemctl enable -q --now netvisor-daemon
echo "NetVisor daemon configured and running"
EOF
chmod +x ~/configure_daemon.sh
msg_ok "Netvisor server running - please create an account in the UI to continue."
motd_ssh
customize
cleanup_lxc

View File

@ -28,8 +28,6 @@ $STD apt install -y \
lsb-release lsb-release
echo 'export PATH=/usr/local:$PATH' >>~/.bashrc echo 'export PATH=/usr/local:$PATH' >>~/.bashrc
echo '# Load PhotoPrism environment variables for CLI tools' >>~/.bashrc
echo 'export $(grep -v "^#" /opt/photoprism/config/.env | xargs)' >>~/.bashrc
export PATH=/usr/local:$PATH export PATH=/usr/local:$PATH
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"

View File

@ -13,11 +13,6 @@ setting_up_container
network_check network_check
update_os update_os
msg_info "Installing Dependencies"
$STD apt install -y rsyslog
systemctl enable -q --now rsyslog
msg_ok "Installed Dependencies"
msg_info "Installing Proxmox Datacenter Manager" msg_info "Installing Proxmox Datacenter Manager"
curl -fsSL https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -o /usr/share/keyrings/proxmox-archive-keyring.gpg curl -fsSL https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg -o /usr/share/keyrings/proxmox-archive-keyring.gpg
setup_deb822_repo \ setup_deb822_repo \
@ -26,21 +21,21 @@ setup_deb822_repo \
"http://download.proxmox.com/debian/pdm" \ "http://download.proxmox.com/debian/pdm" \
"trixie" \ "trixie" \
"pdm-no-subscription" "pdm-no-subscription"
setup_deb822_repo \ cat <<EOF >/etc/apt/sources.list.d/pdm-test.sources
"pdm-test" \ Types: deb
"https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg" \ URIs: http://download.proxmox.com/debian/pdm
"http://download.proxmox.com/debian/pdm" \ Suites: trixie
"trixie" \ Components: pdm-test
"pdm-test" \ Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
"" \ Enabled: false
"false" EOF
$STD apt update
DEBIAN_FRONTEND=noninteractive DEBIAN_FRONTEND=noninteractive
$STD apt -o Dpkg::Options::="--force-confdef" \ $STD apt -o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \ -o Dpkg::Options::="--force-confold" \
install -y proxmox-datacenter-manager \ install -y proxmox-datacenter-manager \
proxmox-datacenter-manager-ui proxmox-datacenter-manager-ui
msg_ok "Installed Proxmox Datacenter Manager" msg_ok "Installed Proxmox Datacenter Manager"
motd_ssh motd_ssh

View File

@ -1,140 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/scanopy/scanopy
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 \
libssl-dev \
pkg-config
msg_ok "Installed Dependencies"
PG_VERSION=17 setup_postgresql
NODE_VERSION="24" setup_nodejs
PG_DB_NAME="scanopy_db" PG_DB_USER="scanopy" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
msg_info "Creating frontend UI"
export PUBLIC_SERVER_HOSTNAME=default
export PUBLIC_SERVER_PORT=""
cd /opt/scanopy/ui
$STD npm ci --no-fund --no-audit
$STD npm run build
msg_ok "Created frontend UI"
msg_info "Building scanopy-server (patience)"
cd /opt/scanopy/backend
$STD cargo build --release --bin server
mv ./target/release/server /usr/bin/scanopy-server
msg_ok "Built scanopy-server"
msg_info "Building scanopy-daemon"
$STD cargo build --release --bin daemon
cp ./target/release/daemon /usr/bin/scanopy-daemon
msg_ok "Built scanopy-daemon"
msg_info "Configuring server for first-run"
LOCAL_IP="$(hostname -I | awk '{print $1}')"
cat <<EOF >/opt/scanopy/.env
### - SERVER
scanopy_DATABASE_URL=postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME
scanopy_WEB_EXTERNAL_PATH="/opt/scanopy/ui/build"
scanopy_PUBLIC_URL=http://${LOCAL_IP}:60072
scanopy_SERVER_PORT=60072
scanopy_LOG_LEVEL=info
scanopy_INTEGRATED_DAEMON_URL=http://127.0.0.1:60073
## - uncomment to disable signups
# scanopy_DISABLE_REGISTRATION=true
## - uncomment when using TLS
# scanopy_USE_SECURE_SESSION_COOKIES=true
## - see https://github.com/imbolc/axum-client-ip?tab=readme-ov-file#configurable-vs-specific-extractors
## - before uncommenting the below
# scanopy_CLIENT_IP_SOURCE=
### - SMTP (password reset and notifications - optional)
# scanopy_SMTP_RELAY=smtp.gmail.com:587
# scanopy_SMTP_USERNAME=your-email@gmail.com
# scanopy_SMTP_PASSWORD=your-app-password
# scanopy_SMTP_EMAIL=scanopy@yourdomain.tld
### - INTEGRATED DAEMON
scanopy_SERVER_URL=http://127.0.0.1:60072
scanopy_BIND_ADDRESS=0.0.0.0
scanopy_NAME="scanopy-daemon"
scanopy_HEARTBEAT_INTERVAL=30
### - see https://github.com/scanopy/scanopy/blob/main/docs/CONFIGURATION.md for more options
EOF
cat <<EOF >/etc/systemd/system/scanopy-server.service
[Unit]
Description=Scanopy Network Discovery Server
After=network.target postgresql.service
[Service]
Type=simple
WorkingDirectory=/opt/scanopy/backend
EnvironmentFile=/opt/scanopy/.env
ExecStart=/usr/bin/scanopy-server
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now scanopy-server
# Creating short script to configure scanopy-daemon
cat <<EOF >~/configure_daemon.sh
#!/usr/bin/env bash
echo "Auto-configuring integrated daemon..."
NETWORK_ID="\$(sudo -u postgres psql -1 -t -d "${PG_DB_NAME}" -c 'SELECT id FROM networks;')"
API_KEY="\$(sudo -u postgres psql -1 -t -d "${PG_DB_NAME}" -c 'SELECT key FROM api_keys;')"
cat <<END >/etc/systemd/system/scanopy-daemon.service
[Unit]
Description=Scanopy Network Discovery Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/scanopy-daemon --server-url http://127.0.0.1:60072 --network-id \${NETWORK_ID} --daemon-api-key \${API_KEY} --mode push
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
END
systemctl enable -q --now scanopy-daemon
echo "Scanopy daemon configured and running"
EOF
chmod +x ~/configure_daemon.sh
msg_ok "Scanopy server running - please create an account in the UI to continue."
motd_ssh
customize
cleanup_lxc

View File

@ -31,7 +31,7 @@ esac
msg_info "Installing Zabbix $ZABBIX_VERSION" msg_info "Installing Zabbix $ZABBIX_VERSION"
cd /tmp cd /tmp
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb" ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
$STD dpkg -i /tmp/zabbix-release_latest+debian13_all.deb $STD dpkg -i /tmp/zabbix-release_latest+debian13_all.deb
$STD apt update $STD apt update

View File

@ -291,90 +291,6 @@ find_host_ssh_keys() {
) )
} }
# ==============================================================================
# SECTION 3B: IP RANGE SCANNING
# ==============================================================================
# ------------------------------------------------------------------------------
# ip_to_int() / int_to_ip()
#
# - Converts IP address to integer and vice versa for range iteration
# ------------------------------------------------------------------------------
ip_to_int() {
local IFS=.
read -r i1 i2 i3 i4 <<<"$1"
echo $(((i1 << 24) + (i2 << 16) + (i3 << 8) + i4))
}
int_to_ip() {
local ip=$1
echo "$(((ip >> 24) & 0xFF)).$(((ip >> 16) & 0xFF)).$(((ip >> 8) & 0xFF)).$((ip & 0xFF))"
}
# ------------------------------------------------------------------------------
# resolve_ip_from_range()
#
# - Takes an IP range in format "10.0.0.1/24-10.0.0.10/24"
# - Pings each IP in the range to find the first available one
# - Returns the first free IP with CIDR notation
# - Sets NET_RESOLVED to the resolved IP or empty on failure
# ------------------------------------------------------------------------------
resolve_ip_from_range() {
local range="$1"
local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
local ip_start ip_end
# Parse range: "10.0.0.1/24-10.0.0.10/24"
ip_start="${range%%-*}"
ip_end="${range##*-}"
if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
NET_RESOLVED=""
return 1
fi
local ip1="${ip_start%%/*}"
local ip2="${ip_end%%/*}"
local cidr="${ip_start##*/}"
local start_int=$(ip_to_int "$ip1")
local end_int=$(ip_to_int "$ip2")
for ((ip_int = start_int; ip_int <= end_int; ip_int++)); do
local ip=$(int_to_ip $ip_int)
msg_info "Checking IP: $ip"
if ! ping -c 1 -W 1 "$ip" >/dev/null 2>&1; then
NET_RESOLVED="$ip/$cidr"
msg_ok "Found free IP: ${BGN}$NET_RESOLVED${CL}"
return 0
fi
done
NET_RESOLVED=""
msg_error "No free IP found in range $range"
return 1
}
# ------------------------------------------------------------------------------
# is_ip_range()
#
# - Checks if a string is an IP range (contains - and looks like IP/CIDR)
# - Returns 0 if it's a range, 1 otherwise
# ------------------------------------------------------------------------------
is_ip_range() {
local value="$1"
local ip_start ip_end
if [[ "$value" == *-* ]] && [[ "$value" != "dhcp" ]]; then
local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
ip_start="${value%%-*}"
ip_end="${value##*-}"
if [[ "$ip_start" =~ $ip_cidr_regex ]] && [[ "$ip_end" =~ $ip_cidr_regex ]]; then
return 0
fi
fi
return 1
}
# ============================================================================== # ==============================================================================
# SECTION 4: STORAGE & RESOURCE MANAGEMENT # SECTION 4: STORAGE & RESOURCE MANAGEMENT
# ============================================================================== # ==============================================================================
@ -487,18 +403,6 @@ base_settings() {
HN=${var_hostname:-$NSAPP} HN=${var_hostname:-$NSAPP}
BRG=${var_brg:-"vmbr0"} BRG=${var_brg:-"vmbr0"}
NET=${var_net:-"dhcp"} NET=${var_net:-"dhcp"}
# Resolve IP range if NET contains a range (e.g., 192.168.1.100/24-192.168.1.200/24)
if is_ip_range "$NET"; then
msg_info "Scanning IP range: $NET"
if resolve_ip_from_range "$NET"; then
NET="$NET_RESOLVED"
else
msg_error "Could not find free IP in range. Falling back to DHCP."
NET="dhcp"
fi
fi
IPV6_METHOD=${var_ipv6_method:-"none"} IPV6_METHOD=${var_ipv6_method:-"none"}
IPV6_STATIC=${var_ipv6_static:-""} IPV6_STATIC=${var_ipv6_static:-""}
GATE=${var_gateway:-""} GATE=${var_gateway:-""}
@ -536,7 +440,6 @@ base_settings() {
ENABLE_MKNOD=${var_mknod:-"0"} ENABLE_MKNOD=${var_mknod:-"0"}
PROTECT_CT=${var_protection:-"no"} PROTECT_CT=${var_protection:-"no"}
CT_TIMEZONE=${var_timezone:-"$timezone"} CT_TIMEZONE=${var_timezone:-"$timezone"}
[[ "${CT_TIMEZONE:-}" == Etc/* ]] && CT_TIMEZONE="host" # pct doesn't accept Etc/* zones
# 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 # 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 if [ -z "$var_os" ]; then
@ -588,12 +491,6 @@ load_vars_file() {
[[ "$var_key" != var_* ]] && continue [[ "$var_key" != var_* ]] && continue
_is_whitelisted "$var_key" || continue _is_whitelisted "$var_key" || continue
# Strip inline comments (anything after unquoted #)
# Only strip if not inside quotes
if [[ ! "$var_val" =~ ^[\"\'] ]]; then
var_val="${var_val%%#*}"
fi
# Strip quotes # Strip quotes
if [[ "$var_val" =~ ^\"(.*)\"$ ]]; then if [[ "$var_val" =~ ^\"(.*)\"$ ]]; then
var_val="${BASH_REMATCH[1]}" var_val="${BASH_REMATCH[1]}"
@ -601,9 +498,6 @@ load_vars_file() {
var_val="${BASH_REMATCH[1]}" var_val="${BASH_REMATCH[1]}"
fi fi
# Trim trailing whitespace
var_val="${var_val%"${var_val##*[![:space:]]}"}"
# Set variable: force mode overrides existing, otherwise only set if empty # Set variable: force mode overrides existing, otherwise only set if empty
if [[ "$force" == "yes" ]]; then if [[ "$force" == "yes" ]]; then
export "${var_key}=${var_val}" export "${var_key}=${var_val}"
@ -1178,10 +1072,7 @@ advanced_settings() {
elif [ -f /etc/timezone ]; then elif [ -f /etc/timezone ]; then
_host_timezone=$(cat /etc/timezone 2>/dev/null || echo "") _host_timezone=$(cat /etc/timezone 2>/dev/null || echo "")
fi fi
# Map Etc/* timezones to "host" (pct doesn't accept Etc/* zones)
[[ "${_host_timezone:-}" == Etc/* ]] && _host_timezone="host"
local _ct_timezone="${var_timezone:-$_host_timezone}" local _ct_timezone="${var_timezone:-$_host_timezone}"
[[ "${_ct_timezone:-}" == Etc/* ]] && _ct_timezone="host"
# Helper to show current progress # Helper to show current progress
show_progress() { show_progress() {
@ -1429,10 +1320,9 @@ advanced_settings() {
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \ if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
--title "IPv4 CONFIGURATION" \ --title "IPv4 CONFIGURATION" \
--ok-button "Next" --cancel-button "Back" \ --ok-button "Next" --cancel-button "Back" \
--menu "\nSelect IPv4 Address Assignment:" 16 65 3 \ --menu "\nSelect IPv4 Address Assignment:" 14 60 2 \
"dhcp" "Automatic (DHCP, recommended)" \ "dhcp" "Automatic (DHCP, recommended)" \
"static" "Static (manual entry)" \ "static" "Static (manual entry)" \
"range" "IP Range Scan (find first free IP)" \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [[ "$result" == "static" ]]; then if [[ "$result" == "static" ]]; then
@ -1463,42 +1353,6 @@ advanced_settings() {
whiptail --msgbox "Invalid IPv4 CIDR format.\nExample: 192.168.1.100/24" 8 58 whiptail --msgbox "Invalid IPv4 CIDR format.\nExample: 192.168.1.100/24" 8 58
fi fi
fi fi
elif [[ "$result" == "range" ]]; then
# IP Range Scan
local ip_range
if ip_range=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
--title "IP RANGE SCAN" \
--ok-button "Scan" --cancel-button "Back" \
--inputbox "\nEnter IP range to scan for free address\n(e.g. 192.168.1.100/24-192.168.1.200/24)" 12 65 "" \
3>&1 1>&2 2>&3); then
if is_ip_range "$ip_range"; then
# Exit whiptail screen temporarily to show scan progress
clear
header_info
echo -e "${INFO}${BOLD}${DGN}Scanning IP range for free address...${CL}\n"
if resolve_ip_from_range "$ip_range"; then
# Get gateway
local gateway_ip
if gateway_ip=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
--title "GATEWAY IP" \
--ok-button "Next" --cancel-button "Back" \
--inputbox "\nFound free IP: $NET_RESOLVED\n\nEnter Gateway IP address" 12 58 "" \
3>&1 1>&2 2>&3); then
if [[ "$gateway_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
_net="$NET_RESOLVED"
_gate=",gw=$gateway_ip"
((STEP++))
else
whiptail --msgbox "Invalid Gateway IP format." 8 58
fi
fi
else
whiptail --msgbox "No free IP found in the specified range.\nAll IPs responded to ping." 10 58
fi
else
whiptail --msgbox "Invalid IP range format.\n\nExample: 192.168.1.100/24-192.168.1.200/24" 10 58
fi
fi
else else
_net="dhcp" _net="dhcp"
_gate="" _gate=""
@ -1838,7 +1692,6 @@ advanced_settings() {
--inputbox "\nSet container timezone.\n\nExamples: Europe/Berlin, America/New_York, Asia/Tokyo\n\nHost timezone: ${_host_timezone:-unknown}\n\nLeave empty to inherit from host." 16 62 "$_ct_timezone" \ --inputbox "\nSet container timezone.\n\nExamples: Europe/Berlin, America/New_York, Asia/Tokyo\n\nHost timezone: ${_host_timezone:-unknown}\n\nLeave empty to inherit from host." 16 62 "$_ct_timezone" \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
_ct_timezone="$result" _ct_timezone="$result"
[[ "${_ct_timezone:-}" == Etc/* ]] && _ct_timezone="host" # pct doesn't accept Etc/* zones
((STEP++)) ((STEP++))
else else
((STEP--)) ((STEP--))
@ -2228,7 +2081,6 @@ install_script() {
else else
timezone="UTC" timezone="UTC"
fi fi
[[ "${timezone:-}" == Etc/* ]] && timezone="host" # pct doesn't accept Etc/* zones
# Show APP Header # Show APP Header
header_info header_info
@ -2830,12 +2682,10 @@ $PCT_OPTIONS_STRING"
-protection 1" -protection 1"
fi fi
# Timezone (map Etc/* to "host" as pct doesn't accept them) # Timezone flag (if var_timezone was set)
if [ -n "${CT_TIMEZONE:-}" ]; then if [ -n "${CT_TIMEZONE:-}" ]; then
local _pct_timezone="$CT_TIMEZONE"
[[ "$_pct_timezone" == Etc/* ]] && _pct_timezone="host"
PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING PCT_OPTIONS_STRING="$PCT_OPTIONS_STRING
-timezone $_pct_timezone" -timezone $CT_TIMEZONE"
fi fi
# Password (already formatted) # Password (already formatted)
@ -3186,9 +3036,8 @@ EOF'
export LANG=\$locale_line" export LANG=\$locale_line"
if [[ -z "${tz:-}" ]]; then if [[ -z "${tz:-}" ]]; then
tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "UTC") tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "Etc/UTC")
fi fi
[[ "${tz:-}" == Etc/* ]] && tz="UTC" # Normalize Etc/* to UTC for container setup
if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
# Set timezone using symlink (Debian 13+ compatible) # Set timezone using symlink (Debian 13+ compatible)

View File

@ -1222,7 +1222,6 @@ setup_deb822_repo() {
local suite="$4" local suite="$4"
local component="${5:-main}" local component="${5:-main}"
local architectures="${6-}" # optional local architectures="${6-}" # optional
local enabled="${7-}" # optional: "true" or "false"
# Validate required parameters # Validate required parameters
if [[ -z "$name" || -z "$gpg_url" || -z "$repo_url" || -z "$suite" ]]; then if [[ -z "$name" || -z "$gpg_url" || -z "$repo_url" || -z "$suite" ]]; then
@ -1256,7 +1255,6 @@ setup_deb822_repo() {
fi fi
[[ -n "$architectures" ]] && echo "Architectures: $architectures" [[ -n "$architectures" ]] && echo "Architectures: $architectures"
echo "Signed-By: /etc/apt/keyrings/${name}.gpg" echo "Signed-By: /etc/apt/keyrings/${name}.gpg"
[[ -n "$enabled" ]] && echo "Enabled: $enabled"
} >/etc/apt/sources.list.d/${name}.sources } >/etc/apt/sources.list.d/${name}.sources
$STD apt update $STD apt update