From 9d0b930db88c3f2ef43d3a0bea54509ff46c1704 Mon Sep 17 00:00:00 2001 From: CanbiZ <47820557+MickLesk@users.noreply.github.com> Date: Mon, 24 Mar 2025 12:00:56 +0100 Subject: [PATCH] Use curl instead of wget --- .../create-ready-for-testing-message.yml | 28 +- .../workflows/scripts/app-test/pr-build.func | 4 +- ct/Deferred/documenso.sh | 78 +- ct/Deferred/hoodik.sh | 78 +- ct/Deferred/koel.sh | 76 +- ct/Deferred/maxun.sh | 2 +- ct/Deferred/nginxproxymanager.sh | 6 +- ct/Deferred/pixelfed.sh | 29 +- ct/Deferred/roundcubemail.sh | 64 +- ct/calibre-web-automated.sh | 100 +- ct/fileflows.sh | 78 +- ct/meilisearch.sh | 118 +- ct/qbittorrent.sh | 74 +- ct/slskd.sh | 92 +- docs/ct/AppName.md | 10 +- docs/install/AppName-install.md | 6 +- docs/install/AppName-install.sh | 20 +- .../ScriptItems/InstallCommand.tsx | 142 +- install/calibre-web-automated-install.sh | 4 +- install/docspell-install.sh | 61 +- install/fileflows-install.sh | 4 +- install/freepbx-install.sh | 5 +- install/frigate-install.sh | 38 +- install/healthchecks-install.sh | 4 +- install/manyfold-install.sh | 2 +- install/meilisearch-install.sh | 6 +- install/qbittorrent-install.sh | 2 +- install/slskd-install.sh | 4 +- install/wazuh-install.sh | 14 +- misc/build.func | 2400 ++++++++--------- misc/install.func | 368 +-- scripts/tools/filebrowser.sh | 175 +- scripts/tools/frigate-support.sh | 18 +- scripts/tools/hw-acceleration.sh | 12 +- scripts/vms/debian-vm-test-helper.sh | 6 +- scripts/vms/debian-vm.sh | 24 +- 36 files changed, 2074 insertions(+), 2078 deletions(-) diff --git a/.github/workflows/create-ready-for-testing-message.yml b/.github/workflows/create-ready-for-testing-message.yml index b965a3a..69cbd1a 100644 --- a/.github/workflows/create-ready-for-testing-message.yml +++ b/.github/workflows/create-ready-for-testing-message.yml @@ -7,7 +7,7 @@ on: permissions: issues: write - + jobs: post_to_discord: runs-on: ubuntu-latest @@ -24,15 +24,15 @@ jobs: run: | REPO="community-scripts/ProxmoxVED" API_URL="https://api.github.com/repos/$REPO/contents" - + FILES=( "ct/${{ env.TITLE }}.sh" "install/${{ env.TITLE }}-install.sh" "frontend/public/json/${{ env.TITLE }}.json" ) - + EXISTING_FILES=() - + for FILE in "${FILES[@]}"; do STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GH_TOKEN" "$API_URL/$FILE") if [ "$STATUS" -eq 200 ]; then @@ -48,26 +48,26 @@ jobs: id: create_message run: | VAR="The ${{ env.TITLE }} script is ready for testing:\n" - VAR+="\`\`\`bash -c \"\$(wget -qLO - https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${{ env.TITLE }}.sh)\"\`\`\`\n" + VAR+="\`\`\`bash -c \"\$(curl -fsSL - https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${{ env.TITLE }}.sh)\"\`\`\`\n" if [[ " ${EXISTING_FILES[@]} " =~ " frontend/public/json/${TITLE}.json " ]]; then - JSON=$(wget -qLO - https://github.com/community-scripts/ProxmoxVED/raw/main/frontend/public/json/${{ env.TITLE }}.json) + JSON=$(curl -fsSL - https://github.com/community-scripts/ProxmoxVED/raw/main/frontend/public/json/${{ env.TITLE }}.json) username=$(echo "$JSON" | jq -r '.default_credentials.username') password=$(echo "$JSON" | jq -r '.default_credentials.password') mapfile -t notes_array < <(echo "$JSON" | jq -r '.notes[].text') - + if [[ -n "$username" && "$username" != "null" || -n "$password" && "$password" != "null" ]]; then VAR+="Default credentials:\n" - + if [[ -n "$username" && "$username" != "null" ]]; then VAR+="Username: $username\n" fi - + if [[ -n "$password" && "$password" != "null" ]]; then VAR+="Password: $password\n" fi VAR+="\n" fi - + if [ ${#notes_array[@]} -gt 0 ]; then for note in "${notes_array[@]}"; do VAR+="$note\n" @@ -79,7 +79,7 @@ jobs: VAR+="Discussion & issue tracking:\n" VAR+="${{ github.event.issue.html_url }}" echo "message=$VAR" >> $GITHUB_ENV - + - name: Create a forumpost in Discord id: post_to_discord env: @@ -90,12 +90,12 @@ jobs: run: | JSON_PAYLOAD=$(jq -n --arg name "Wanted Tester for $TITLE" --arg content "$MESSAGE" '{name: $name, message: {content: $content | gsub("\\\\n"; "\n")}, applied_tags: []}') echo "JSON Payload: $JSON_PAYLOAD" - + RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "https://discord.com/api/v10/channels/$DISCORD_CHANNEL_ID/threads" \ -H "Authorization: Bot $DISCORD_BOT_TOKEN" \ -H "Content-Type: application/json" \ -d "$JSON_PAYLOAD") - + STATUS_CODE=$(echo "$RESPONSE" | tail -n 1) if [ "$STATUS_CODE" -eq 201 ]; then echo "Discord post created successfully!" @@ -104,7 +104,7 @@ jobs: echo "Failed to create Discord post! Status code: $STATUS_CODE" exit 1 fi - + - name: Comment on Issue id: comment_on_issue env: diff --git a/.github/workflows/scripts/app-test/pr-build.func b/.github/workflows/scripts/app-test/pr-build.func index 67a9767..59f091b 100644 --- a/.github/workflows/scripts/app-test/pr-build.func +++ b/.github/workflows/scripts/app-test/pr-build.func @@ -184,7 +184,7 @@ build_container() { echo "Container ID: $CTID" # This executes create_lxc.sh and creates the container and .conf file - bash -c "$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-create-lxc.sh)" + bash -c "$(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-create-lxc.sh)" LXC_CONFIG=/etc/pve/lxc/${CTID}.conf if [ "$CT_TYPE" == "0" ]; then @@ -257,4 +257,4 @@ EOF' description() { IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) -} \ No newline at end of file +} diff --git a/ct/Deferred/documenso.sh b/ct/Deferred/documenso.sh index fc9650f..39f3856 100644 --- a/ct/Deferred/documenso.sh +++ b/ct/Deferred/documenso.sh @@ -20,46 +20,46 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/documenso ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -s https://api.github.com/repos/documenso/documenso/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75 - msg_info "Stopping ${APP}" - systemctl stop documenso - msg_ok "${APP} Stopped" - - msg_info "Updating ${APP} to ${RELEASE}" - cp /opt/documenso/.env /opt/ - rm -R /opt/documenso - wget -q "https://github.com/documenso/documenso/archive/refs/tags/v${RELEASE}.zip" - unzip -q v${RELEASE}.zip - mv documenso-${RELEASE} /opt/documenso - cd /opt/documenso - mv /opt/.env /opt/documenso/.env - npm install &>/dev/null - npm run build:web &>/dev/null - npm run prisma:migrate-deploy &>/dev/null - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Updated ${APP}" - - msg_info "Starting ${APP}" - systemctl start documenso - msg_ok "Started ${APP}" - - msg_info "Cleaning Up" - rm -rf v${RELEASE}.zip - msg_ok "Cleaned" - msg_ok "Updated Successfully" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/documenso ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + RELEASE=$(curl -s https://api.github.com/repos/documenso/documenso/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75 + msg_info "Stopping ${APP}" + systemctl stop documenso + msg_ok "${APP} Stopped" + + msg_info "Updating ${APP} to ${RELEASE}" + cp /opt/documenso/.env /opt/ + rm -R /opt/documenso + curl -fsSL "https://github.com/documenso/documenso/archive/refs/tags/v${RELEASE}.zip" + unzip -q v${RELEASE}.zip + mv documenso-${RELEASE} /opt/documenso + cd /opt/documenso + mv /opt/.env /opt/documenso/.env + npm install &>/dev/null + npm run build:web &>/dev/null + npm run prisma:migrate-deploy &>/dev/null + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated ${APP}" + + msg_info "Starting ${APP}" + systemctl start documenso + msg_ok "Started ${APP}" + + msg_info "Cleaning Up" + rm -rf v${RELEASE}.zip + msg_ok "Cleaned" + msg_ok "Updated Successfully" + else + msg_ok "No update required. ${APP} is already at ${RELEASE}" + fi + exit } start diff --git a/ct/Deferred/hoodik.sh b/ct/Deferred/hoodik.sh index d0b4088..4efb63f 100644 --- a/ct/Deferred/hoodik.sh +++ b/ct/Deferred/hoodik.sh @@ -21,46 +21,46 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/hoodik ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -s https://api.github.com/repos/hudikhq/hoodik/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Stopping Services" - systemctl stop hoodik - msg_ok "Services Stopped" - - msg_info "Updating ${APP} to ${RELEASE}" - cd /opt - if [ -d hoodik_bak ]; then - rm -rf hoodik_bak - fi - mv hoodik hoodik_bak - wget -q "https://github.com/hudikhq/hoodik/archive/refs/tags/${RELEASE}.zip" - unzip -q ${RELEASE}.zip - mv hoodik-${RELEASE} /opt/hoodik - cd /opt/hoodik - cargo update -q - cargo build -q --release - msg_ok "Updated Hoodik" - - msg_info "Starting Services" - systemctl start hoodik - msg_ok "Started Services" - - msg_info "Cleaning Up" - rm -R /opt/${RELEASE}.zip - rm -R /opt/hoodik_bak - msg_ok "Cleaned" - msg_ok "Updated Successfully" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/hoodik ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + RELEASE=$(curl -s https://api.github.com/repos/hudikhq/hoodik/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Stopping Services" + systemctl stop hoodik + msg_ok "Services Stopped" + + msg_info "Updating ${APP} to ${RELEASE}" + cd /opt + if [ -d hoodik_bak ]; then + rm -rf hoodik_bak + fi + mv hoodik hoodik_bak + curl -fsSL "https://github.com/hudikhq/hoodik/archive/refs/tags/${RELEASE}.zip" + unzip -q ${RELEASE}.zip + mv hoodik-${RELEASE} /opt/hoodik + cd /opt/hoodik + cargo update -q + cargo build -q --release + msg_ok "Updated Hoodik" + + msg_info "Starting Services" + systemctl start hoodik + msg_ok "Started Services" + + msg_info "Cleaning Up" + rm -R /opt/${RELEASE}.zip + rm -R /opt/hoodik_bak + msg_ok "Cleaned" + msg_ok "Updated Successfully" + else + msg_ok "No update required. ${APP} is already at ${RELEASE}" + fi + exit } start diff --git a/ct/Deferred/koel.sh b/ct/Deferred/koel.sh index 394083a..50744db 100644 --- a/ct/Deferred/koel.sh +++ b/ct/Deferred/koel.sh @@ -24,45 +24,45 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/koel ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -s https://api.github.com/repos/koel/koel/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Stopping ${APP} Service" - systemctl stop nginx - msg_ok "Stopped ${APP} Service" - - msg_info "Updating ${APP} to v${RELEASE}" - cd /opt - wget -q https://github.com/koel/koel/releases/download/${RELEASE}/koel-${RELEASE}.zip - unzip -q koel-${RELEASE}.zip - cd /opt/koel - composer update --no-interaction >/dev/null 2>&1 - composer install --no-interaction >/dev/null 2>&1 - php artisan migrate --force >/dev/null 2>&1 - php artisan cache:clear >/dev/null 2>&1 - php artisan config:clear >/dev/null 2>&1 - php artisan view:clear >/dev/null 2>&1 - php artisan koel:init --no-interaction >/dev/null 2>&1 - msg_ok "Updated ${APP} to v${RELEASE}" - - msg_info "Starting ${APP} Service" - systemctl start nginx - msg_ok "Started ${APP} Service" - - msg_info "Cleaning up" - rm -rf /opt/koel-${RELEASE}.zip - msg_ok "Cleaned" - msg_ok "Updated Successfully!\n" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/koel ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + RELEASE=$(curl -s https://api.github.com/repos/koel/koel/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Stopping ${APP} Service" + systemctl stop nginx + msg_ok "Stopped ${APP} Service" + + msg_info "Updating ${APP} to v${RELEASE}" + cd /opt + curl -fsSL https://github.com/koel/koel/releases/download/${RELEASE}/koel-${RELEASE}.zip + unzip -q koel-${RELEASE}.zip + cd /opt/koel + composer update --no-interaction >/dev/null 2>&1 + composer install --no-interaction >/dev/null 2>&1 + php artisan migrate --force >/dev/null 2>&1 + php artisan cache:clear >/dev/null 2>&1 + php artisan config:clear >/dev/null 2>&1 + php artisan view:clear >/dev/null 2>&1 + php artisan koel:init --no-interaction >/dev/null 2>&1 + msg_ok "Updated ${APP} to v${RELEASE}" + + msg_info "Starting ${APP} Service" + systemctl start nginx + msg_ok "Started ${APP} Service" + + msg_info "Cleaning up" + rm -rf /opt/koel-${RELEASE}.zip + msg_ok "Cleaned" + msg_ok "Updated Successfully!\n" + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/ct/Deferred/maxun.sh b/ct/Deferred/maxun.sh index b0d2d41..31733a4 100644 --- a/ct/Deferred/maxun.sh +++ b/ct/Deferred/maxun.sh @@ -36,7 +36,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" mv /opt/maxun /opt/maxun_bak cd /opt - wget -q "https://github.com/getmaxun/maxun/archive/refs/tags/v${RELEASE}.zip" + curl -fsSL "https://github.com/getmaxun/maxun/archive/refs/tags/v${RELEASE}.zip" unzip -q v${RELEASE}.zip mv maxun-${RELEASE} /opt/maxun mv /opt/maxun_bak/.env /opt/maxun/ diff --git a/ct/Deferred/nginxproxymanager.sh b/ct/Deferred/nginxproxymanager.sh index a2a8518..df50ac2 100644 --- a/ct/Deferred/nginxproxymanager.sh +++ b/ct/Deferred/nginxproxymanager.sh @@ -14,7 +14,7 @@ var_os="debian" var_version="12" var_unprivileged="1" -header_info "$APP" +header_info "$APP" variables color catch_errors @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - if ! command -v pnpm &> /dev/null; then + if ! command -v pnpm &>/dev/null; then msg_info "Installing pnpm" #export NODE_OPTIONS=--openssl-legacy-provider $STD npm install -g pnpm@8.15 @@ -51,7 +51,7 @@ function update_script() { msg_ok "Cleaned Old Files" msg_info "Downloading NPM v${RELEASE}" - wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz + curl -fsSL https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz cd nginx-proxy-manager-${RELEASE} msg_ok "Downloaded NPM v${RELEASE}" diff --git a/ct/Deferred/pixelfed.sh b/ct/Deferred/pixelfed.sh index d85e27f..0814424 100644 --- a/ct/Deferred/pixelfed.sh +++ b/ct/Deferred/pixelfed.sh @@ -19,22 +19,21 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -d /opt/pixelfed ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - RELEASE=$(curl -s https://api.github.com/repos/xxxx/xxxx/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Updating ${APP} to ${RELEASE}" - cd /opt - wget -q - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pixelfed ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + RELEASE=$(curl -s https://api.github.com/repos/xxxx/xxxx/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Updating ${APP} to ${RELEASE}" + cd /opt + else + msg_ok "No update required. ${APP} is already at ${RELEASE}" + fi + exit } start diff --git a/ct/Deferred/roundcubemail.sh b/ct/Deferred/roundcubemail.sh index ec72259..9882143 100644 --- a/ct/Deferred/roundcubemail.sh +++ b/ct/Deferred/roundcubemail.sh @@ -20,39 +20,39 @@ color catch_errors function update_script() { - header_info - if [[ ! -d /opt/roundcubemail ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - if (($(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80)); then - read -r -p "Warning: Storage is dangerously low, continue anyway? " prompt - [[ ${prompt,,} =~ ^(y|yes)$ ]] || exit - fi - RELEASE=$(curl -s https://api.github.com/repos/roundcube/roundcubemail/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Updating ${APP} to ${RELEASE}" - cd /opt - wget -q "https://github.com/roundcube/roundcubemail/releases/download/${RELEASE}/roundcubemail-${RELEASE}-complete.tar.gz" - tar -xf roundcubemail-${RELEASE}-complete.tar.gz - mv roundcubemail-${RELEASE} /opt/roundcubemail - cd /opt/roundcubemail - COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev - chown -R www-data:www-data temp/ logs/ - msg_ok "Updated ${APP}" - - msg_info "Reload Apache2" - systemctl reload apache2 - msg_ok "Apache2 Reloaded" - - msg_info "Cleaning Up" - rm -rf /opt/roundcubemail-${RELEASE}-complete.tar.gz - msg_ok "Cleaned" - msg_ok "Updated Successfully" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi + header_info + if [[ ! -d /opt/roundcubemail ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + if (($(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80)); then + read -r -p "Warning: Storage is dangerously low, continue anyway? " prompt + [[ ${prompt,,} =~ ^(y|yes)$ ]] || exit + fi + RELEASE=$(curl -s https://api.github.com/repos/roundcube/roundcubemail/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Updating ${APP} to ${RELEASE}" + cd /opt + curl -fsSL "https://github.com/roundcube/roundcubemail/releases/download/${RELEASE}/roundcubemail-${RELEASE}-complete.tar.gz" + tar -xf roundcubemail-${RELEASE}-complete.tar.gz + mv roundcubemail-${RELEASE} /opt/roundcubemail + cd /opt/roundcubemail + COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev + chown -R www-data:www-data temp/ logs/ + msg_ok "Updated ${APP}" + + msg_info "Reload Apache2" + systemctl reload apache2 + msg_ok "Apache2 Reloaded" + + msg_info "Cleaning Up" + rm -rf /opt/roundcubemail-${RELEASE}-complete.tar.gz + msg_ok "Cleaned" + msg_ok "Updated Successfully" + else + msg_ok "No update required. ${APP} is already at ${RELEASE}" + fi + exit } start diff --git a/ct/calibre-web-automated.sh b/ct/calibre-web-automated.sh index fa9da2f..dae78e4 100644 --- a/ct/calibre-web-automated.sh +++ b/ct/calibre-web-automated.sh @@ -20,58 +20,58 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -d /opt/cwa ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - RELEASE=$(curl -s https://api.github.com/repos/crocodilestick/Calibre-Web-Automated/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') - if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - msg_info "Stopping $APP" - systemctl stop cps cwa-autolibrary cwa-ingester cwa-change-detector cwa-autozip.timer - msg_ok "Stopped $APP" - - msg_info "Creating Backup" - $STD tar -czf "/opt/${APP}_backup_$(date +%F).tar.gz" /opt/cwa /opt/calibre-web/metadata.db - msg_ok "Backup Created" - - msg_info "Updating $APP to v${RELEASE}" - cd /opt/kepubify - rm -rf kepubify-linux-64bit - curl -fsSLO https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-64bit - chmod +x kepubify-linux-64bit - cd /opt/calibre-web - $STD pip install --upgrade calibreweb[goodreads,metadata,kobo] - cd /opt/cwa - $STD git stash --all - $STD git pull - $STD pip install -r requirements.txt - wget -q https://gist.githubusercontent.com/vhsdream/2e81afeff139c5746db1ede88c01cc7b/raw/51238206e87aec6c0abeccce85dec9f2b0c89000/proxmox-lxc.patch -O /opt/cwa.patch # not for production - $STD git apply --whitespace=fix /opt/cwa.patch # not for production - cp -r /opt/cwa/root/app/calibre-web/cps/* /usr/local/lib/python3*/dist-packages/calibreweb/cps - cd scripts - chmod +x check-cwa-services.sh ingest-service.sh change-detector.sh - msg_ok "Updated $APP to v${RELEASE}" - - msg_info "Starting $APP" - systemctl start cps cwa-autolibrary cwa-ingester cwa-change-detector cwa-autozip.timer - msg_ok "Started $APP" - - msg_info "Cleaning Up" - rm -rf /opt/cwa.patch - rm -rf "/opt/${APP}_backup_$(date +%F).tar.gz" - msg_ok "Cleanup Completed" - - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + if [[ ! -d /opt/cwa ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + RELEASE=$(curl -s https://api.github.com/repos/crocodilestick/Calibre-Web-Automated/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then + msg_info "Stopping $APP" + systemctl stop cps cwa-autolibrary cwa-ingester cwa-change-detector cwa-autozip.timer + msg_ok "Stopped $APP" + + msg_info "Creating Backup" + $STD tar -czf "/opt/${APP}_backup_$(date +%F).tar.gz" /opt/cwa /opt/calibre-web/metadata.db + msg_ok "Backup Created" + + msg_info "Updating $APP to v${RELEASE}" + cd /opt/kepubify + rm -rf kepubify-linux-64bit + curl -fsSLO https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-64bit + chmod +x kepubify-linux-64bit + cd /opt/calibre-web + $STD pip install --upgrade calibreweb[goodreads,metadata,kobo] + cd /opt/cwa + $STD git stash --all + $STD git pull + $STD pip install -r requirements.txt + curl -fsSL https://gist.githubusercontent.com/vhsdream/2e81afeff139c5746db1ede88c01cc7b/raw/51238206e87aec6c0abeccce85dec9f2b0c89000/proxmox-lxc.patch -O /opt/cwa.patch # not for production + $STD git apply --whitespace=fix /opt/cwa.patch # not for production + cp -r /opt/cwa/root/app/calibre-web/cps/* /usr/local/lib/python3*/dist-packages/calibreweb/cps + cd scripts + chmod +x check-cwa-services.sh ingest-service.sh change-detector.sh + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting $APP" + systemctl start cps cwa-autolibrary cwa-ingester cwa-change-detector cwa-autozip.timer + msg_ok "Started $APP" + + msg_info "Cleaning Up" + rm -rf /opt/cwa.patch + rm -rf "/opt/${APP}_backup_$(date +%F).tar.gz" + msg_ok "Cleanup Completed" + + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Update Successful" + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/ct/fileflows.sh b/ct/fileflows.sh index 697d1cf..7cafe68 100644 --- a/ct/fileflows.sh +++ b/ct/fileflows.sh @@ -20,47 +20,47 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - - if [[ ! -d /opt/fileflows ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - update_available=$(curl -s -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable) - if [[ "${update_available}" == "true" ]]; then - msg_info "Stopping $APP" - systemctl stop fileflows - msg_ok "Stopped $APP" - - msg_info "Creating Backup" - backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz" - tar -czf $backup_filename -C /opt/fileflows Data - msg_ok "Backup Created" - - msg_info "Updating $APP to latest version" - temp_file=$(mktemp) - wget -q https://fileflows.com/downloads/zip -O $temp_file - unzip -oq -d /opt/fileflows $temp_file - msg_ok "Updated $APP to latest version" - - msg_info "Starting $APP" - systemctl start fileflows - msg_ok "Started $APP" - - msg_info "Cleaning Up" - rm -rf $temp_file - rm -rf $backup_filename - msg_ok "Cleanup Completed" - - msg_ok "Update Successful" - else - msg_ok "No update required. ${APP} is already at latest version" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/fileflows ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + update_available=$(curl -s -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable) + if [[ "${update_available}" == "true" ]]; then + msg_info "Stopping $APP" + systemctl stop fileflows + msg_ok "Stopped $APP" + + msg_info "Creating Backup" + backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz" + tar -czf $backup_filename -C /opt/fileflows Data + msg_ok "Backup Created" + + msg_info "Updating $APP to latest version" + temp_file=$(mktemp) + curl -fsSL https://fileflows.com/downloads/zip -O $temp_file + unzip -oq -d /opt/fileflows $temp_file + msg_ok "Updated $APP to latest version" + + msg_info "Starting $APP" + systemctl start fileflows + msg_ok "Started $APP" + + msg_info "Cleaning Up" + rm -rf $temp_file + rm -rf $backup_filename + msg_ok "Cleanup Completed" + + msg_ok "Update Successful" + else + msg_ok "No update required. ${APP} is already at latest version" + fi + + exit } start diff --git a/ct/meilisearch.sh b/ct/meilisearch.sh index 0c6ed43..96fe45e 100644 --- a/ct/meilisearch.sh +++ b/ct/meilisearch.sh @@ -20,69 +20,69 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -f /opt/meilisearch_version.txt ]]; then - msg_error "No Meilisearch Installation Found!" - exit + if [[ ! -f /opt/meilisearch_version.txt ]]; then + msg_error "No Meilisearch Installation Found!" + exit + fi + UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Meilisearch Update" --radiolist --cancel-button Exit-Script "Spacebar = Select" 10 58 2 \ + "1" "Update Meilisearch" ON \ + "2" "Update Meilisearch-UI" OFF \ + 3>&1 1>&2 2>&3) + + if [ "$UPD" == "1" ]; then + msg_info "Stopping Meilisearch" + systemctl stop meilisearch + msg_ok "Stopped Meilisearch" + + msg_info "Updating Meilisearch" + tmp_file=$(mktemp) + RELEASE=$(curl -s https://api.github.com/repos/meilisearch/meilisearch/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + curl -fsSL https://github.com/meilisearch/meilisearch/releases/latest/download/meilisearch.deb -O $tmp_file + $STD dpkg -i $tmp_file + echo "$RELEASE" >/opt/meilisearch_version.txt + msg_ok "Updated Meilisearch" + + msg_info "Starting Meilisearch" + systemctl start meilisearch + msg_ok "Started Meilisearch" + exit + fi + + if [ "$UPD" == "2" ]; then + if [[ ! -f /opt/meilisearch-ui_version.txt ]]; then + msg_error "No Meilisearch-UI Installation Found!" + exit fi - UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Meilisearch Update" --radiolist --cancel-button Exit-Script "Spacebar = Select" 10 58 2 \ - "1" "Update Meilisearch" ON \ - "2" "Update Meilisearch-UI" OFF \ - 3>&1 1>&2 2>&3) + msg_info "Stopping Meilisearch-UI" + systemctl stop meilisearch-ui + msg_ok "Stopped Meilisearch-UI" - if [ "$UPD" == "1" ]; then - msg_info "Stopping Meilisearch" - systemctl stop meilisearch - msg_ok "Stopped Meilisearch" + msg_info "Updating Meilisearch-UI" + tmp_file=$(mktemp) + tmp_dir=$(mktemp -d) + RELEASE_UI=$(curl -s https://api.github.com/repos/riccox/meilisearch-ui/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + cp /opt/meilisearch-ui/.env.local /tmp/.env.local.bak + rm -rf /opt/meilisearch-ui + mkdir -p /opt/meilisearch-ui + curl -fsSL "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -O $tmp_file + unzip -q "$tmp_file" -d "$tmp_dir" + mv "$tmp_dir"/*/* /opt/meilisearch-ui/ + cd /opt/meilisearch-ui + sed -i 's|const hash = execSync("git rev-parse HEAD").toString().trim();|const hash = "unknown";|' /opt/meilisearch-ui/vite.config.ts + mv /tmp/.env.local.bak /opt/meilisearch-ui/.env.local + $STD pnpm install + echo "$RELEASE_UI" >/opt/meilisearch-ui_version.txt + msg_ok "Updated Meilisearch-UI" - msg_info "Updating Meilisearch" - tmp_file=$(mktemp) - RELEASE=$(curl -s https://api.github.com/repos/meilisearch/meilisearch/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - wget -q https://github.com/meilisearch/meilisearch/releases/latest/download/meilisearch.deb -O $tmp_file - $STD dpkg -i $tmp_file - echo "$RELEASE" >/opt/meilisearch_version.txt - msg_ok "Updated Meilisearch" - - msg_info "Starting Meilisearch" - systemctl start meilisearch - msg_ok "Started Meilisearch" - exit - fi - - if [ "$UPD" == "2" ]; then - if [[ ! -f /opt/meilisearch-ui_version.txt ]]; then - msg_error "No Meilisearch-UI Installation Found!" - exit - fi - msg_info "Stopping Meilisearch-UI" - systemctl stop meilisearch-ui - msg_ok "Stopped Meilisearch-UI" - - msg_info "Updating Meilisearch-UI" - tmp_file=$(mktemp) - tmp_dir=$(mktemp -d) - RELEASE_UI=$(curl -s https://api.github.com/repos/riccox/meilisearch-ui/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - cp /opt/meilisearch-ui/.env.local /tmp/.env.local.bak - rm -rf /opt/meilisearch-ui - mkdir -p /opt/meilisearch-ui - wget -q "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -O $tmp_file - unzip -q "$tmp_file" -d "$tmp_dir" - mv "$tmp_dir"/*/* /opt/meilisearch-ui/ - cd /opt/meilisearch-ui - sed -i 's|const hash = execSync("git rev-parse HEAD").toString().trim();|const hash = "unknown";|' /opt/meilisearch-ui/vite.config.ts - mv /tmp/.env.local.bak /opt/meilisearch-ui/.env.local - $STD pnpm install - echo "$RELEASE_UI" >/opt/meilisearch-ui_version.txt - msg_ok "Updated Meilisearch-UI" - - msg_info "Starting Meilisearch-UI" - systemctl start meilisearch-ui - msg_ok "Started Meilisearch-UI" - exit - fi + msg_info "Starting Meilisearch-UI" + systemctl start meilisearch-ui + msg_ok "Started Meilisearch-UI" + exit + fi } start diff --git a/ct/qbittorrent.sh b/ct/qbittorrent.sh index 0488833..867b576 100644 --- a/ct/qbittorrent.sh +++ b/ct/qbittorrent.sh @@ -20,44 +20,44 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources - if [[ ! -f /etc/systemd/system/qbittorrent-nox.service ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - if [[ ! -f /opt/${APP}_version.txt ]]; then - touch /opt/${APP}_version.txt - mkdir -p $HOME/.config/qBittorrent/ - mkdir -p /opt/qbittorrent/ - mv /.config/qBittorrent $HOME/.config/ - $STD apt-get remove --purge -y qbittorrent-nox - sed -i 's@ExecStart=/usr/bin/qbittorrent-nox@ExecStart=/opt/qbittorrent/qbittorrent-nox@g' /etc/systemd/system/qbittorrent-nox.service - systemctl daemon-reload - fi - FULLRELEASE=$(curl -s https://api.github.com/repos/userdocs/qbittorrent-nox-static/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - RELEASE=$(echo $FULLRELEASE | cut -c 9-13) - if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_info "Stopping Service" - systemctl stop qbittorrent-nox - msg_ok "Stopped Service" - - msg_info "Updating ${APP} to v${RELEASE}" - rm -f /opt/qbittorrent/qbittorrent-nox - wget -q "https://github.com/userdocs/qbittorrent-nox-static/releases/download/${FULLRELEASE}/x86_64-qbittorrent-nox" -O /opt/qbittorrent/qbittorrent-nox - chmod +x /opt/qbittorrent/qbittorrent-nox - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Updated $APP to v${RELEASE}" - - msg_info "Starting Service" - systemctl start qbittorrent-nox - msg_ok "Started Service" - msg_ok "Updated Successfully" - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + header_info + check_container_storage + check_container_resources + if [[ ! -f /etc/systemd/system/qbittorrent-nox.service ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + if [[ ! -f /opt/${APP}_version.txt ]]; then + touch /opt/${APP}_version.txt + mkdir -p $HOME/.config/qBittorrent/ + mkdir -p /opt/qbittorrent/ + mv /.config/qBittorrent $HOME/.config/ + $STD apt-get remove --purge -y qbittorrent-nox + sed -i 's@ExecStart=/usr/bin/qbittorrent-nox@ExecStart=/opt/qbittorrent/qbittorrent-nox@g' /etc/systemd/system/qbittorrent-nox.service + systemctl daemon-reload + fi + FULLRELEASE=$(curl -s https://api.github.com/repos/userdocs/qbittorrent-nox-static/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + RELEASE=$(echo $FULLRELEASE | cut -c 9-13) + if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then + msg_info "Stopping Service" + systemctl stop qbittorrent-nox + msg_ok "Stopped Service" + + msg_info "Updating ${APP} to v${RELEASE}" + rm -f /opt/qbittorrent/qbittorrent-nox + curl -fsSL "https://github.com/userdocs/qbittorrent-nox-static/releases/download/${FULLRELEASE}/x86_64-qbittorrent-nox" -O /opt/qbittorrent/qbittorrent-nox + chmod +x /opt/qbittorrent/qbittorrent-nox + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting Service" + systemctl start qbittorrent-nox + msg_ok "Started Service" + msg_ok "Updated Successfully" + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/ct/slskd.sh b/ct/slskd.sh index f0d5639..29b54f6 100644 --- a/ct/slskd.sh +++ b/ct/slskd.sh @@ -20,54 +20,54 @@ color catch_errors function update_script() { - header_info - check_container_storage - check_container_resources + header_info + check_container_storage + check_container_resources - if [[ ! -d /opt/slskd ]] || [[ ! -d /opt/soularr ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - RELEASE=$(curl -s https://api.github.com/repos/slskd/slskd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then - msg_info "Stopping $APP and Soularr" - systemctl stop slskd soularr.timer soularr.service - msg_ok "Stopped $APP and Soularr" - - msg_info "Updating $APP to v${RELEASE}" - tmp_file=$(mktemp) - wget -q "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -O $tmp_file - unzip -q -oj $tmp_file slskd -d /opt/${APP} - echo "${RELEASE}" >/opt/${APP}_version.txt - msg_ok "Updated $APP to v${RELEASE}" - - msg_info "Updating Soularr" - cp /opt/soularr/config.ini /opt/config.ini.bak - cp /opt/soularr/run.sh /opt/run.sh.bak - cd /tmp - rm -rf /opt/soularr - wget -q https://github.com/mrusse/soularr/archive/refs/heads/main.zip - unzip -q main.zip - mv soularr-main /opt/soularr - cd /opt/soularr - $STD pip install -r requirements.txt - mv /opt/config.ini.bak /opt/soularr/config.ini - mv /opt/run.sh.bak /opt/soularr/run.sh - msg_ok "Soularr updated" - msg_info "Starting $APP and Soularr" - systemctl start slskd soularr.timer - msg_ok "Started $APP and Soularr" - - msg_info "Cleaning Up" - rm -rf $tmp_file - rm -rf /tmp/main.zip - msg_ok "Cleanup Completed" - - else - msg_ok "No update required. ${APP} is already at v${RELEASE}" - fi + if [[ ! -d /opt/slskd ]] || [[ ! -d /opt/soularr ]]; then + msg_error "No ${APP} Installation Found!" exit + fi + + RELEASE=$(curl -s https://api.github.com/repos/slskd/slskd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') + if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then + msg_info "Stopping $APP and Soularr" + systemctl stop slskd soularr.timer soularr.service + msg_ok "Stopped $APP and Soularr" + + msg_info "Updating $APP to v${RELEASE}" + tmp_file=$(mktemp) + curl -fsSL "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -O $tmp_file + unzip -q -oj $tmp_file slskd -d /opt/${APP} + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Updating Soularr" + cp /opt/soularr/config.ini /opt/config.ini.bak + cp /opt/soularr/run.sh /opt/run.sh.bak + cd /tmp + rm -rf /opt/soularr + curl -fsSL https://github.com/mrusse/soularr/archive/refs/heads/main.zip + unzip -q main.zip + mv soularr-main /opt/soularr + cd /opt/soularr + $STD pip install -r requirements.txt + mv /opt/config.ini.bak /opt/soularr/config.ini + mv /opt/run.sh.bak /opt/soularr/run.sh + msg_ok "Soularr updated" + msg_info "Starting $APP and Soularr" + systemctl start slskd soularr.timer + msg_ok "Started $APP and Soularr" + + msg_info "Cleaning Up" + rm -rf $tmp_file + rm -rf /tmp/main.zip + msg_ok "Cleanup Completed" + + else + msg_ok "No update required. ${APP} is already at v${RELEASE}" + fi + exit } start diff --git a/docs/ct/AppName.md b/docs/ct/AppName.md index f6f9420..d334b0c 100644 --- a/docs/ct/AppName.md +++ b/docs/ct/AppName.md @@ -40,7 +40,7 @@ - Import the build.func file. - When developing your own script, change the URL to your own repository. -> [!IMPORTANT] +> [!IMPORTANT] > You also need to change all apperances of this URL in `misc/build.func` and `misc/install.func` Example for development: @@ -95,7 +95,7 @@ Example: >| Variable | Description | Notes | >|----------|-------------|-------| >| `APP` | Application name | Must match ct\AppName.sh | ->| `var_tags` | Proxmox display tags without Spaces, only ; | Limit the number | +>| `var_tags` | Proxmox display tags without Spaces, only ; | Limit the number | >| `var_cpu` | CPU cores | Number of cores | >| `var_ram` | RAM | In MB | >| `var_disk` | Disk capacity | In GB | @@ -189,7 +189,7 @@ Example with a Github Release: Example: ```bash -wget -q +curl -fsSL unzip -q ``` @@ -198,8 +198,8 @@ unzip -q Example: ```bash -$STD php artisan migrate --force -$STD php artisan config:clear +$STD php artisan migrate --force +$STD php artisan config:clear ``` ### 3.5 **Backups** diff --git a/docs/install/AppName-install.md b/docs/install/AppName-install.md index 42107fd..376956d 100644 --- a/docs/install/AppName-install.md +++ b/docs/install/AppName-install.md @@ -115,7 +115,7 @@ $STD apt-get install -y \ git \ sudo \ mc \ - nginx + nginx ``` ### 3.2 **Collapse dependencies** @@ -154,7 +154,7 @@ Example for a git release: ```bash RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" +curl -fsSL "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" ``` ### 5.2 **Save the version for update checks** @@ -192,7 +192,7 @@ msg_ok "Installed Dependencies" Example: ```bash -wget -q +curl -fsSL unzip -q ``` diff --git a/docs/install/AppName-install.sh b/docs/install/AppName-install.sh index 43ea76a..01d725d 100644 --- a/docs/install/AppName-install.sh +++ b/docs/install/AppName-install.sh @@ -6,7 +6,7 @@ # Source: [SOURCE_URL] # Import Functions und Setup -source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" color verb_ip6 catch_errors @@ -34,11 +34,11 @@ $STD mysql -u root -e "CREATE DATABASE $DB_NAME;" $STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$DB_PASS');" $STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;" { - echo "${APPLICATION} Credentials" - echo "Database User: $DB_USER" - echo "Database Password: $DB_PASS" - echo "Database Name: $DB_NAME" -} >> ~/$APP_NAME.creds + echo "${APPLICATION} Credentials" + echo "Database User: $DB_USER" + echo "Database Password: $DB_PASS" + echo "Database Name: $DB_NAME" +} >>~/$APP_NAME.creds msg_ok "Set up Database" # Temp @@ -46,11 +46,11 @@ msg_ok "Set up Database" # Setup App msg_info "Setup ${APPLICATION}" RELEASE=$(curl -s https://api.github.com/repos/[REPO]/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -wget -q "https://github.com/[REPO]/archive/refs/tags/${RELEASE}.zip" +curl -fsSL "https://github.com/[REPO]/archive/refs/tags/${RELEASE}.zip" unzip -q ${RELEASE}.zip mv ${APPLICATION}-${RELEASE}/ /opt/${APPLICATION} -# -# +# +# # echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Setup ${APPLICATION}" @@ -80,4 +80,4 @@ msg_info "Cleaning up" rm -f ${RELEASE}.zip $STD apt-get -y autoremove $STD apt-get -y autoclean -msg_ok "Cleaned" \ No newline at end of file +msg_ok "Cleaned" diff --git a/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx b/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx index 26d941c..0ce2306 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx @@ -4,82 +4,82 @@ import { basePath } from "@/config/siteConfig"; import { Script } from "@/lib/types"; import { getDisplayValueFromType } from "../ScriptInfoBlocks"; -const getInstallCommand = (scriptPath?: string, isAlpine = false) => { - return `bash -c "$(wget -q${isAlpine ? "" : "L"}O - https://github.com/community-scripts/${basePath}/raw/main/${scriptPath})"`; +const getInstallCommand = (scriptPath = "") => { + return `bash -c "$(curl -fsSL https://github.com/community-scripts/${basePath}/raw/main/${scriptPath})"`; }; export default function InstallCommand({ item }: { item: Script }) { - const alpineScript = item.install_methods.find( - (method) => method.type === "alpine", - ); + const alpineScript = item.install_methods.find( + (method) => method.type === "alpine", + ); - const defaultScript = item.install_methods.find( - (method) => method.type === "default", - ); + const defaultScript = item.install_methods.find( + (method) => method.type === "default", + ); - const renderInstructions = (isAlpine = false) => ( - <> -

- {isAlpine ? ( - <> - As an alternative option, you can use Alpine Linux and the{" "} - {item.name} package to create a {item.name}{" "} - {getDisplayValueFromType(item.type)} container with faster creation - time and minimal system resource usage. You are also obliged to - adhere to updates provided by the package maintainer. - - ) : item.type == "misc" ? ( - <> - To use the {item.name} script, run the command below in the shell. - - ) : ( - <> - {" "} - To create a new Proxmox VE {item.name}{" "} - {getDisplayValueFromType(item.type)}, run the command below in the - Proxmox VE Shell. - - )} -

- {isAlpine && ( -

- To create a new Proxmox VE Alpine-{item.name}{" "} - {getDisplayValueFromType(item.type)}, run the command below in the - Proxmox VE Shell -

- )} - - ); - - return ( -
- {alpineScript ? ( - - - Default - Alpine Linux - - - {renderInstructions()} - - {getInstallCommand(defaultScript?.script)} - - - - {renderInstructions(true)} - - {getInstallCommand(alpineScript.script, true)} - - - - ) : defaultScript?.script ? ( + const renderInstructions = (isAlpine = false) => ( <> - {renderInstructions()} - - {getInstallCommand(defaultScript.script)} - +

+ {isAlpine ? ( + <> + As an alternative option, you can use Alpine Linux and the{" "} + {item.name} package to create a {item.name}{" "} + {getDisplayValueFromType(item.type)} container with faster creation + time and minimal system resource usage. You are also obliged to + adhere to updates provided by the package maintainer. + + ) : item.type == "misc" ? ( + <> + To use the {item.name} script, run the command below in the shell. + + ) : ( + <> + {" "} + To create a new Proxmox VE {item.name}{" "} + {getDisplayValueFromType(item.type)}, run the command below in the + Proxmox VE Shell. + + )} +

+ {isAlpine && ( +

+ To create a new Proxmox VE Alpine-{item.name}{" "} + {getDisplayValueFromType(item.type)}, run the command below in the + Proxmox VE Shell +

+ )} - ) : null} -
- ); + ); + + return ( +
+ {alpineScript ? ( + + + Default + Alpine Linux + + + {renderInstructions()} + + {getInstallCommand(defaultScript?.script)} + + + + {renderInstructions(true)} + + {getInstallCommand(alpineScript.script, true)} + + + + ) : defaultScript?.script ? ( + <> + {renderInstructions()} + + {getInstallCommand(defaultScript.script)} + + + ) : null} +
+ ); } diff --git a/install/calibre-web-automated-install.sh b/install/calibre-web-automated-install.sh index f9a8cf4..2206679 100644 --- a/install/calibre-web-automated-install.sh +++ b/install/calibre-web-automated-install.sh @@ -47,7 +47,7 @@ msg_info "Installing Calibre-Web (Patience)" rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED mkdir -p /opt/calibre-web $STD apt-get install -y calibre -$STD wget https://github.com/janeczku/calibre-web/raw/master/library/metadata.db -P /opt/calibre-web +$STD curl -fsSL -o /opt/calibre-web/metadata.db https://github.com/janeczku/calibre-web/raw/master/library/metadata.db $STD pip install calibreweb[goodreads,metadata,kobo] $STD pip install jsonschema msg_ok "Installed Calibre-Web" @@ -81,7 +81,7 @@ $STD git clone https://github.com/crocodilestick/Calibre-Web-Automated.git /opt/ cd /opt/cwa $STD git checkout V${RELEASE} $STD pip install -r requirements.txt -wget -q https://gist.githubusercontent.com/vhsdream/2e81afeff139c5746db1ede88c01cc7b/raw/51238206e87aec6c0abeccce85dec9f2b0c89000/proxmox-lxc.patch -O /opt/cwa.patch # not for production +curl -fsSL https://gist.githubusercontent.com/vhsdream/2e81afeff139c5746db1ede88c01cc7b/raw/51238206e87aec6c0abeccce85dec9f2b0c89000/proxmox-lxc.patch -O /opt/cwa.patch # not for production $STD git apply --whitespace=fix /opt/cwa.patch # not for production cd scripts chmod +x check-cwa-services.sh ingest-service.sh change-detector.sh diff --git a/install/docspell-install.sh b/install/docspell-install.sh index 15676a4..e253f0a 100644 --- a/install/docspell-install.sh +++ b/install/docspell-install.sh @@ -15,26 +15,25 @@ update_os msg_info "Installing Dependencies (Patience)" $STD apt-get install -y \ - unzip \ - htop \ - gnupg2 \ - ca-certificates \ - default-jdk \ - apt-transport-https \ - ghostscript \ - tesseract-ocr \ - tesseract-ocr-deu \ - tesseract-ocr-eng \ - unpaper \ - unoconv \ - wkhtmltopdf \ - ocrmypdf \ - wget \ - zip \ - curl \ - sudo \ - make \ - mc + unzip \ + htop \ + gnupg2 \ + ca-certificates \ + default-jdk \ + apt-transport-https \ + ghostscript \ + tesseract-ocr \ + tesseract-ocr-deu \ + tesseract-ocr-eng \ + unpaper \ + unoconv \ + wkhtmltopdf \ + ocrmypdf \ + zip \ + curl \ + sudo \ + make \ + mc msg_ok "Installed Dependencies" msg_info "Setting up PostgreSQL Repository" @@ -54,27 +53,27 @@ $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8' $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';" $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';" { - echo "Docspell-Credentials" - echo "Docspell Database Name: $DB_NAME" - echo "Docspell Database User: $DB_USER" - echo "Docspell Database Password: $DB_PASS" + echo "Docspell-Credentials" + echo "Docspell Database Name: $DB_NAME" + echo "Docspell Database User: $DB_USER" + echo "Docspell Database Password: $DB_PASS" } >>~/docspell.creds msg_ok "Set up PostgreSQL Database" msg_info "Setup Docspell (Patience)" mkdir -p /opt/docspell -Docspell=$(wget -q https://github.com/eikek/docspell/releases/latest -O - | grep "title>Release" | cut -d " " -f 5) -DocspellDSC=$(wget -q https://github.com/docspell/dsc/releases/latest -O - | grep "title>Release" | cut -d " " -f 4 | sed 's/^v//') +Docspell=$(curl -fsSL https://github.com/eikek/docspell/releases/latest -O - | grep "title>Release" | cut -d " " -f 5) +DocspellDSC=$(curl -fsSL https://github.com/docspell/dsc/releases/latest -O - | grep "title>Release" | cut -d " " -f 4 | sed 's/^v//') cd /opt -wget -q https://github.com/eikek/docspell/releases/download/v${Docspell}/docspell-joex_${Docspell}_all.deb -wget -q https://github.com/eikek/docspell/releases/download/v${Docspell}/docspell-restserver_${Docspell}_all.deb +curl -fsSL https://github.com/eikek/docspell/releases/download/v${Docspell}/docspell-joex_${Docspell}_all.deb +curl -fsSL https://github.com/eikek/docspell/releases/download/v${Docspell}/docspell-restserver_${Docspell}_all.deb $STD dpkg -i docspell-*.deb -wget -q https://github.com/docspell/dsc/releases/download/v${DocspellDSC}/dsc_amd64-musl-${DocspellDSC} +curl -fsSL https://github.com/docspell/dsc/releases/download/v${DocspellDSC}/dsc_amd64-musl-${DocspellDSC} mv dsc_amd* dsc chmod +x dsc mv dsc /usr/bin ln -s /etc/docspell-joex /opt/docspell/docspell-joex && ln -s /etc/docspell-restserver /opt/docspell/docspell-restserver && ln -s /usr/bin/dsc /opt/docspell/dsc -wget -q https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq +curl -fsSL https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq chmod +x /usr/bin/yq JOEX_CONF="/usr/share/docspell-joex/conf/docspell-joex.conf" SERVER_CONF="/usr/share/docspell-restserver/conf/docspell-server.conf" @@ -105,7 +104,7 @@ cd /opt/docspell SOLR_DOWNLOAD_URL="https://downloads.apache.org/lucene/solr/" latest_version=$(curl -s "$SOLR_DOWNLOAD_URL" | grep -oP '(?<=[0-9])' | head -n 1) download_url="${SOLR_DOWNLOAD_URL}${latest_version}/solr-${latest_version}.tgz" -wget -q "$download_url" +curl -fsSL "$download_url" tar xzf "solr-$latest_version.tgz" $STD bash "/opt/docspell/solr-$latest_version/bin/install_solr_service.sh" "solr-$latest_version.tgz" mv /opt/solr /opt/docspell/solr diff --git a/install/fileflows-install.sh b/install/fileflows-install.sh index 8eb883b..a254c4a 100644 --- a/install/fileflows-install.sh +++ b/install/fileflows-install.sh @@ -45,7 +45,7 @@ fi msg_ok "Installed and Set Up Intel Hardware Acceleration" msg_info "Installing ASP.NET Core Runtime" -wget -q https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +curl -fsSL https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb $STD dpkg -i packages-microsoft-prod.deb rm -rf packages-microsoft-prod.deb $STD apt-get update @@ -56,7 +56,7 @@ msg_info "Setup ${APPLICATION}" $STD ln -svf /usr/bin/ffmpeg /usr/local/bin/ffmpeg $STD ln -svf /usr/bin/ffprobe /usr/local/bin/ffprobe temp_file=$(mktemp) -wget -q https://fileflows.com/downloads/zip -O $temp_file +curl -fsSL https://fileflows.com/downloads/zip -O $temp_file unzip -q -d /opt/fileflows $temp_file (cd /opt/fileflows/Server && dotnet FileFlows.Server.dll --systemd install --root true) systemctl enable -q --now fileflows.service diff --git a/install/freepbx-install.sh b/install/freepbx-install.sh index b81f798..ff88391 100644 --- a/install/freepbx-install.sh +++ b/install/freepbx-install.sh @@ -20,7 +20,6 @@ $STD apt-get install -y \ mc \ build-essential \ git \ - wget \ libnewt-dev \ libssl-dev \ libncurses5-dev \ @@ -79,7 +78,7 @@ msg_ok "Installed Dependencies" msg_info "Installing Asterisk (Patience)" cd /usr/src -wget -q http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-21-current.tar.gz +curl -fsSL http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-21-current.tar.gz tar xf asterisk-21-current.tar.gz cd asterisk-21.* $STD contrib/scripts/get_mp3_source.sh @@ -138,7 +137,7 @@ EOF msg_info "Installing FreePBX" cd /usr/local/src -wget -q http://mirror.freepbx.org/modules/packages/freepbx/freepbx-17.0-latest-EDGE.tgz +curl -fsSL http://mirror.freepbx.org/modules/packages/freepbx/freepbx-17.0-latest-EDGE.tgz tar zxf freepbx-17.0-latest-EDGE.tgz cd /usr/local/src/freepbx/ $STD ./start_asterisk start diff --git a/install/frigate-install.sh b/install/frigate-install.sh index 527c031..bcd44e9 100644 --- a/install/frigate-install.sh +++ b/install/frigate-install.sh @@ -15,16 +15,16 @@ update_os msg_info "Installing Dependencies (Patience)" $STD apt-get install -y \ - curl sudo mc git gpg ca-certificates automake build-essential xz-utils libtool ccache pkg-config \ - libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev \ - libjpeg-dev libpng-dev libtiff-dev gfortran openexr libatlas-base-dev libssl-dev libtbb-dev \ - libopenexr-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev gcc gfortran \ - libopenblas-dev liblapack-dev libusb-1.0-0-dev jq moreutils tclsh libhdf5-dev libopenexr-dev + curl sudo mc git gpg ca-certificates automake build-essential xz-utils libtool ccache pkg-config \ + libgtk-3-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev \ + libjpeg-dev libpng-dev libtiff-dev gfortran openexr libatlas-base-dev libssl-dev libtbb-dev \ + libopenexr-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev gcc gfortran \ + libopenblas-dev liblapack-dev libusb-1.0-0-dev jq moreutils tclsh libhdf5-dev libopenexr-dev msg_ok "Installed Dependencies" msg_info "Setup Python3" $STD apt-get install -y \ - python3 python3-dev python3-setuptools python3-distutils python3-pip + python3 python3-dev python3-setuptools python3-distutils python3-pip $STD pip install --upgrade pip msg_ok "Setup Python3" @@ -39,7 +39,7 @@ msg_ok "Installed Node.js" msg_info "Installing go2rtc" mkdir -p /usr/local/go2rtc/bin cd /usr/local/go2rtc/bin -wget -qO go2rtc "https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_amd64" +curl -fsSL "https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_amd64" -o go2rtc chmod +x go2rtc ln -sf /usr/local/go2rtc/bin/go2rtc /usr/local/bin/go2rtc msg_ok "Installed go2rtc" @@ -47,16 +47,16 @@ msg_ok "Installed go2rtc" msg_info "Setting Up Hardware Acceleration" $STD apt-get -y install {va-driver-all,ocl-icd-libopencl1,intel-opencl-icd,vainfo,intel-gpu-tools} if [[ "$CTTYPE" == "0" ]]; then - chgrp video /dev/dri - chmod 755 /dev/dri - chmod 660 /dev/dri/* + chgrp video /dev/dri + chmod 755 /dev/dri + chmod 660 /dev/dri/* fi msg_ok "Set Up Hardware Acceleration" msg_info "Setup Frigate" RELEASE=$(curl -s https://api.github.com/repos/blakeblackshear/frigate/releases/latest | jq -r '.tag_name') mkdir -p /opt/frigate/models -wget -q https://github.com/blakeblackshear/frigate/archive/refs/tags/${RELEASE}.tar.gz -O frigate.tar.gz +curl -fsSL https://github.com/blakeblackshear/frigate/archive/refs/tags/${RELEASE}.tar.gz -O frigate.tar.gz tar -xzf frigate.tar.gz -C /opt/frigate --strip-components 1 rm -rf frigate.tar.gz cd /opt/frigate @@ -102,21 +102,21 @@ cameras: EOF ln -sf /config/config.yml /opt/frigate/config/config.yml if [[ "$CTTYPE" == "0" ]]; then - sed -i -e 's/^kvm:x:104:$/render:x:104:root,frigate/' -e 's/^render:x:105:root$/kvm:x:105:/' /etc/group + sed -i -e 's/^kvm:x:104:$/render:x:104:root,frigate/' -e 's/^render:x:105:root$/kvm:x:105:/' /etc/group else - sed -i -e 's/^kvm:x:104:$/render:x:104:frigate/' -e 's/^render:x:105:$/kvm:x:105:/' /etc/group + sed -i -e 's/^kvm:x:104:$/render:x:104:frigate/' -e 's/^render:x:105:$/kvm:x:105:/' /etc/group fi echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab msg_ok "Installed Frigate $RELEASE" read -p "Semantic Search requires a dedicated GPU and at least 16GB RAM. Would you like to install it? (y/n): " semantic_choice if [[ "$semantic_choice" == "y" ]]; then - msg_info "Configuring Semantic Search & AI Models" - mkdir -p /opt/frigate/models/semantic_search - wget -qO /opt/frigate/models/semantic_search/clip_model.pt https://huggingface.co/openai/clip-vit-base-patch32/resolve/main/pytorch_model.bin - msg_ok "Semantic Search Models Installed" + msg_info "Configuring Semantic Search & AI Models" + mkdir -p /opt/frigate/models/semantic_search + curl -fsSL -o /opt/frigate/models/semantic_search/clip_model.pt https://huggingface.co/openai/clip-vit-base-patch32/resolve/main/pytorch_model.bin + msg_ok "Semantic Search Models Installed" else - msg_ok "Skipped Semantic Search Setup" + msg_ok "Skipped Semantic Search Setup" fi msg_info "Building and Installing libUSB without udev" wget -qO /tmp/libusb.zip https://github.com/libusb/libusb/archive/v1.0.26.zip @@ -134,7 +134,7 @@ msg_info "Installing Coral Object Detection Model (Patience)" cd /opt/frigate export CCACHE_DIR=/root/.ccache export CCACHE_MAXSIZE=2G -wget -q https://github.com/libusb/libusb/archive/v1.0.26.zip +curl -fsSL https://github.com/libusb/libusb/archive/v1.0.26.zip unzip -q v1.0.26.zip rm v1.0.26.zip cd libusb-1.0.26 diff --git a/install/healthchecks-install.sh b/install/healthchecks-install.sh index ba68fe6..a86a794 100644 --- a/install/healthchecks-install.sh +++ b/install/healthchecks-install.sh @@ -60,7 +60,7 @@ msg_ok "Set up Database" msg_info "Setup healthchecks" cd /opt RELEASE=$(curl -s https://api.github.com/repos/healthchecks/healthchecks/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -wget -q "https://github.com/healthchecks/healthchecks/archive/refs/tags/v${RELEASE}.zip" +curl -fsSL "https://github.com/healthchecks/healthchecks/archive/refs/tags/v${RELEASE}.zip" unzip -q v${RELEASE}.zip mv healthchecks-${RELEASE} /opt/healthchecks cd /opt/healthchecks @@ -127,4 +127,4 @@ msg_info "Cleaning up" rm -rf /opt/v${RELEASE}.zip $STD apt-get -y autoremove $STD apt-get -y autoclean -msg_ok "Cleaned" \ No newline at end of file +msg_ok "Cleaned" diff --git a/install/manyfold-install.sh b/install/manyfold-install.sh index 0e0fb8e..fb40223 100644 --- a/install/manyfold-install.sh +++ b/install/manyfold-install.sh @@ -67,7 +67,7 @@ msg_ok "Added manyfold user" msg_info "Installing Manyfold" RELEASE=$(curl -s https://api.github.com/repos/manyfold3d/manyfold/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') cd /opt -wget -q "https://github.com/manyfold3d/manyfold/archive/refs/tags/v${RELEASE}.zip" +curl -fsSL "https://github.com/manyfold3d/manyfold/archive/refs/tags/v${RELEASE}.zip" unzip -q "v${RELEASE}.zip" mv /opt/manyfold-${RELEASE}/ /opt/manyfold cd /opt/manyfold diff --git a/install/meilisearch-install.sh b/install/meilisearch-install.sh index 4fdafd1..830ac08 100644 --- a/install/meilisearch-install.sh +++ b/install/meilisearch-install.sh @@ -24,9 +24,9 @@ msg_ok "Installed Dependencies" msg_info "Setup ${APPLICATION}" tmp_file=$(mktemp) RELEASE=$(curl -s https://api.github.com/repos/meilisearch/meilisearch/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -wget -q https://github.com/meilisearch/meilisearch/releases/latest/download/meilisearch.deb -O $tmp_file +curl -fsSL https://github.com/meilisearch/meilisearch/releases/latest/download/meilisearch.deb -O $tmp_file $STD dpkg -i $tmp_file -wget -q https://raw.githubusercontent.com/meilisearch/meilisearch/latest/config.toml -O /etc/meilisearch.toml +curl -fsSL https://raw.githubusercontent.com/meilisearch/meilisearch/latest/config.toml -O /etc/meilisearch.toml MASTER_KEY=$(openssl rand -base64 12) LOCAL_IP="$(hostname -I | awk '{print $1}')" sed -i \ @@ -60,7 +60,7 @@ if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then tmp_dir=$(mktemp -d) mkdir -p /opt/meilisearch-ui RELEASE_UI=$(curl -s https://api.github.com/repos/riccox/meilisearch-ui/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - wget -q "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -O $tmp_file + curl -fsSL "https://github.com/riccox/meilisearch-ui/archive/refs/tags/${RELEASE_UI}.zip" -O $tmp_file unzip -q "$tmp_file" -d "$tmp_dir" mv "$tmp_dir"/*/* /opt/meilisearch-ui/ cd /opt/meilisearch-ui diff --git a/install/qbittorrent-install.sh b/install/qbittorrent-install.sh index 7dd7df1..ceacfdc 100644 --- a/install/qbittorrent-install.sh +++ b/install/qbittorrent-install.sh @@ -24,7 +24,7 @@ msg_info "Setup qBittorrent-nox" FULLRELEASE=$(curl -s https://api.github.com/repos/userdocs/qbittorrent-nox-static/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') RELEASE=$(echo $RELEASE | cut -c 9-13) mkdir -p /opt/qbittorrent -wget -q "https://github.com/userdocs/qbittorrent-nox-static/releases/download/${FULLRELEASE}/x86_64-qbittorrent-nox -O /opt/qbittorrent/qbittorrent-nox" +curl -fsSL "https://github.com/userdocs/qbittorrent-nox-static/releases/download/${FULLRELEASE}/x86_64-qbittorrent-nox -O /opt/qbittorrent/qbittorrent-nox" chmod +x /opt/qbittorrent/qbittorrent-nox mkdir -p $HOME/.config/qBittorrent/ cat <$HOME/.config/qBittorrent/qBittorrent.conf diff --git a/install/slskd-install.sh b/install/slskd-install.sh index 32363c7..984056c 100644 --- a/install/slskd-install.sh +++ b/install/slskd-install.sh @@ -25,7 +25,7 @@ msg_ok "Installed Dependencies" msg_info "Setup ${APPLICATION}" tmp_file=$(mktemp) RELEASE=$(curl -s https://api.github.com/repos/slskd/slskd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -wget -q "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -O $tmp_file +curl -fsSL "https://github.com/slskd/slskd/releases/download/${RELEASE}/slskd-${RELEASE}-linux-x64.zip" -O $tmp_file unzip -q $tmp_file -d /opt/${APPLICATION} echo "${RELEASE}" >/opt/${APPLICATION}_version.txt JWT_KEY=$(openssl rand -base64 44) @@ -45,7 +45,7 @@ msg_ok "Setup ${APPLICATION}" msg_info "Installing Soularr" rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED cd /tmp -wget -q https://github.com/mrusse/soularr/archive/refs/heads/main.zip +curl -fsSL https://github.com/mrusse/soularr/archive/refs/heads/main.zip unzip -q main.zip mv soularr-main /opt/soularr cd /opt/soularr diff --git a/install/wazuh-install.sh b/install/wazuh-install.sh index 00309bc..8b3cc05 100644 --- a/install/wazuh-install.sh +++ b/install/wazuh-install.sh @@ -15,9 +15,9 @@ update_os msg_info "Installing Dependencies" $STD apt-get install -y \ - sudo \ - mc \ - curl + sudo \ + mc \ + curl msg_ok "Installed Dependencies" # Fetching the latest Wazuh version @@ -26,15 +26,15 @@ RELEASE=$(curl -s https://api.github.com/repos/wazuh/wazuh/releases/latest | gre msg_ok "Latest Wazuh Version: $RELEASE" msg_info "Setup Wazuh" -wget -q https://packages.wazuh.com/$RELEASE/wazuh-install.sh +curl -fsSL https://packages.wazuh.com/$RELEASE/wazuh-install.sh chmod +x wazuh-install.sh if [ "$STD" = "silent" ]; then - bash wazuh-install.sh -a >> ~/wazuh-install.output + bash wazuh-install.sh -a >>~/wazuh-install.output else - bash wazuh-install.sh -a | tee -a ~/wazuh-install.output + bash wazuh-install.sh -a | tee -a ~/wazuh-install.output fi -cat ~/wazuh-install.output | grep -E "User|Password" | awk '{$1=$1};1' | sed '1i wazuh-credentials' > ~/wazuh.creds +cat ~/wazuh-install.output | grep -E "User|Password" | awk '{$1=$1};1' | sed '1i wazuh-credentials' >~/wazuh.creds msg_ok "Setup Wazuh" motd_ssh diff --git a/misc/build.func b/misc/build.func index cc1addb..2eb3593 100644 --- a/misc/build.func +++ b/misc/build.func @@ -5,853 +5,853 @@ # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE variables() { - NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces. - var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP. - INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern. - PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase - DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call. - METHOD="default" # sets the METHOD variable to "default", used for the API call. - RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable. + NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces. + var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP. + INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern. + PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase + DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call. + METHOD="default" # sets the METHOD variable to "default", used for the API call. + RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable. } source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) # This function sets various color variables using ANSI escape codes for formatting text in the terminal. color() { - # Colors - YW=$(echo "\033[33m") - YWB=$(echo "\033[93m") - BL=$(echo "\033[36m") - RD=$(echo "\033[01;31m") - BGN=$(echo "\033[4;92m") - GN=$(echo "\033[1;92m") - DGN=$(echo "\033[32m") + # Colors + YW=$(echo "\033[33m") + YWB=$(echo "\033[93m") + BL=$(echo "\033[36m") + RD=$(echo "\033[01;31m") + BGN=$(echo "\033[4;92m") + GN=$(echo "\033[1;92m") + DGN=$(echo "\033[32m") - # Formatting - CL=$(echo "\033[m") - UL=$(echo "\033[4m") - BOLD=$(echo "\033[1m") - BFR="\\r\\033[K" - HOLD=" " - TAB=" " + # Formatting + CL=$(echo "\033[m") + UL=$(echo "\033[4m") + BOLD=$(echo "\033[1m") + BFR="\\r\\033[K" + HOLD=" " + TAB=" " - # Icons - CM="${TAB}✔️${TAB}${CL}" - CROSS="${TAB}✖️${TAB}${CL}" - INFO="${TAB}💡${TAB}${CL}" - OS="${TAB}🖥️${TAB}${CL}" - OSVERSION="${TAB}🌟${TAB}${CL}" - CONTAINERTYPE="${TAB}📦${TAB}${CL}" - DISKSIZE="${TAB}💾${TAB}${CL}" - CPUCORE="${TAB}🧠${TAB}${CL}" - RAMSIZE="${TAB}🛠️${TAB}${CL}" - SEARCH="${TAB}🔍${TAB}${CL}" - VERIFYPW="${TAB}🔐${TAB}${CL}" - CONTAINERID="${TAB}🆔${TAB}${CL}" - HOSTNAME="${TAB}🏠${TAB}${CL}" - BRIDGE="${TAB}🌉${TAB}${CL}" - NETWORK="${TAB}📡${TAB}${CL}" - GATEWAY="${TAB}🌐${TAB}${CL}" - DISABLEIPV6="${TAB}🚫${TAB}${CL}" - DEFAULT="${TAB}⚙️${TAB}${CL}" - MACADDRESS="${TAB}🔗${TAB}${CL}" - VLANTAG="${TAB}🏷️${TAB}${CL}" - ROOTSSH="${TAB}🔑${TAB}${CL}" - CREATING="${TAB}🚀${TAB}${CL}" - ADVANCED="${TAB}🧩${TAB}${CL}" - CIFS="${TAB}🔌${TAB}${CL}" - FUSE="${TAB}🔧${TAB}${CL}" - NFS="${TAB}📂${TAB}${CL}" + # Icons + CM="${TAB}✔️${TAB}${CL}" + CROSS="${TAB}✖️${TAB}${CL}" + INFO="${TAB}💡${TAB}${CL}" + OS="${TAB}🖥️${TAB}${CL}" + OSVERSION="${TAB}🌟${TAB}${CL}" + CONTAINERTYPE="${TAB}📦${TAB}${CL}" + DISKSIZE="${TAB}💾${TAB}${CL}" + CPUCORE="${TAB}🧠${TAB}${CL}" + RAMSIZE="${TAB}🛠️${TAB}${CL}" + SEARCH="${TAB}🔍${TAB}${CL}" + VERIFYPW="${TAB}🔐${TAB}${CL}" + CONTAINERID="${TAB}🆔${TAB}${CL}" + HOSTNAME="${TAB}🏠${TAB}${CL}" + BRIDGE="${TAB}🌉${TAB}${CL}" + NETWORK="${TAB}📡${TAB}${CL}" + GATEWAY="${TAB}🌐${TAB}${CL}" + DISABLEIPV6="${TAB}🚫${TAB}${CL}" + DEFAULT="${TAB}⚙️${TAB}${CL}" + MACADDRESS="${TAB}🔗${TAB}${CL}" + VLANTAG="${TAB}🏷️${TAB}${CL}" + ROOTSSH="${TAB}🔑${TAB}${CL}" + CREATING="${TAB}🚀${TAB}${CL}" + ADVANCED="${TAB}🧩${TAB}${CL}" + CIFS="${TAB}🔌${TAB}${CL}" + FUSE="${TAB}🔧${TAB}${CL}" + NFS="${TAB}📂${TAB}${CL}" } # This function enables error handling in the script by setting options and defining a trap for the ERR signal. catch_errors() { - set -Eeuo pipefail - trap 'error_handler $LINENO "$BASH_COMMAND"' ERR + set -Eeuo pipefail + trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } # This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message. error_handler() { - source /dev/stdin <<<$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi - printf "\e[?25h" - local exit_code="$?" - local line_number="$1" - local command="$2" - local error_description="$(get_error_description "$exit_code")" - local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL} (${YW}$error_description${CL}): while executing command ${YW}$command${CL}" - post_update_to_api "failed" "$exit_code" "$error_description" - echo -e "\n$error_message\n" + source /dev/stdin <<<$(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi + printf "\e[?25h" + local exit_code="$?" + local line_number="$1" + local command="$2" + local error_description="$(get_error_description "$exit_code")" + local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL} (${YW}$error_description${CL}): while executing command ${YW}$command${CL}" + post_update_to_api "failed" "$exit_code" "$error_description" + echo -e "\n$error_message\n" } # This function displays an informational message with logging support. start_spinner() { - local msg="$1" - local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') - local spin_i=0 - local interval=0.1 - local term_width=$(tput cols) + local msg="$1" + local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') + local spin_i=0 + local interval=0.1 + local term_width=$(tput cols) - { - while [ "${SPINNER_ACTIVE:-1}" -eq 1 ]; do - printf "\r\e[2K${frames[spin_i]} ${YW}%b${CL}" "$msg" >&2 - spin_i=$(((spin_i + 1) % ${#frames[@]})) - sleep "$interval" - done - } & + { + while [ "${SPINNER_ACTIVE:-1}" -eq 1 ]; do + printf "\r\e[2K${frames[spin_i]} ${YW}%b${CL}" "$msg" >&2 + spin_i=$(((spin_i + 1) % ${#frames[@]})) + sleep "$interval" + done + } & - SPINNER_PID=$! + SPINNER_PID=$! } msg_info() { - local msg="$1" - if [ "${SPINNER_ACTIVE:-0}" -eq 1 ]; then - return - fi + local msg="$1" + if [ "${SPINNER_ACTIVE:-0}" -eq 1 ]; then + return + fi - SPINNER_ACTIVE=1 - start_spinner "$msg" + SPINNER_ACTIVE=1 + start_spinner "$msg" } msg_ok() { - if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then - kill "$SPINNER_PID" >/dev/null 2>&1 - wait "$SPINNER_PID" 2>/dev/null || true - fi + if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then + kill "$SPINNER_PID" >/dev/null 2>&1 + wait "$SPINNER_PID" 2>/dev/null || true + fi - local msg="$1" - printf "\r\e[2K${CM}${GN}%b${CL}\n" "$msg" >&2 - unset SPINNER_PID - SPINNER_ACTIVE=0 + local msg="$1" + printf "\r\e[2K${CM}${GN}%b${CL}\n" "$msg" >&2 + unset SPINNER_PID + SPINNER_ACTIVE=0 - log_message "OK" "$msg" + log_message "OK" "$msg" } msg_error() { - if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then - kill "$SPINNER_PID" >/dev/null 2>&1 - wait "$SPINNER_PID" 2>/dev/null || true - fi + if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then + kill "$SPINNER_PID" >/dev/null 2>&1 + wait "$SPINNER_PID" 2>/dev/null || true + fi - local msg="$1" - printf "\r\e[2K${CROSS}${RD}%b${CL}\n" "$msg" >&2 - unset SPINNER_PID - SPINNER_ACTIVE=0 - log_message "ERROR" "$msg" + local msg="$1" + printf "\r\e[2K${CROSS}${RD}%b${CL}\n" "$msg" >&2 + unset SPINNER_PID + SPINNER_ACTIVE=0 + log_message "ERROR" "$msg" } log_message() { - local level="$1" - local message="$2" - local timestamp - local logdate - timestamp=$(date '+%Y-%m-%d %H:%M:%S') - logdate=$(date '+%Y-%m-%d') + local level="$1" + local message="$2" + local timestamp + local logdate + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + logdate=$(date '+%Y-%m-%d') - LOGDIR="/usr/local/community-scripts/logs" - mkdir -p "$LOGDIR" + LOGDIR="/usr/local/community-scripts/logs" + mkdir -p "$LOGDIR" - LOGFILE="${LOGDIR}/${logdate}_${NSAPP}.log" - echo "$timestamp - $level: $message" >>"$LOGFILE" + LOGFILE="${LOGDIR}/${logdate}_${NSAPP}.log" + echo "$timestamp - $level: $message" >>"$LOGFILE" } # Check if the shell is using bash shell_check() { - if [[ "$(basename "$SHELL")" != "bash" ]]; then - clear - msg_error "Your default shell is currently not set to Bash. To use these scripts, please switch to the Bash shell." - echo -e "\nExiting..." - sleep 2 - exit - fi + if [[ "$(basename "$SHELL")" != "bash" ]]; then + clear + msg_error "Your default shell is currently not set to Bash. To use these scripts, please switch to the Bash shell." + echo -e "\nExiting..." + sleep 2 + exit + fi } # Run as root only root_check() { - if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then - clear - msg_error "Please run this script as root." - echo -e "\nExiting..." - sleep 2 - exit - fi + if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then + clear + msg_error "Please run this script as root." + echo -e "\nExiting..." + sleep 2 + exit + fi } # This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported. pve_check() { - if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then - msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported" - echo -e "Requires Proxmox Virtual Environment Version 8.1 or later." - echo -e "Exiting..." - sleep 2 - exit - fi + if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then + msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported" + echo -e "Requires Proxmox Virtual Environment Version 8.1 or later." + echo -e "Exiting..." + sleep 2 + exit + fi } # When a node is running tens of containers, it's possible to exceed the kernel's cryptographic key storage allocations. # These are tuneable, so verify if the currently deployment is approaching the limits, advise the user on how to tune the limits, and exit the script. # https://cleveruptime.com/docs/files/proc-key-users | https://docs.kernel.org/security/keys/core.html maxkeys_check() { - # Read kernel parameters - per_user_maxkeys=$(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 0) - per_user_maxbytes=$(cat /proc/sys/kernel/keys/maxbytes 2>/dev/null || echo 0) + # Read kernel parameters + per_user_maxkeys=$(cat /proc/sys/kernel/keys/maxkeys 2>/dev/null || echo 0) + per_user_maxbytes=$(cat /proc/sys/kernel/keys/maxbytes 2>/dev/null || echo 0) - # Exit if kernel parameters are unavailable - if [[ "$per_user_maxkeys" -eq 0 || "$per_user_maxbytes" -eq 0 ]]; then - echo -e "${CROSS}${RD} Error: Unable to read kernel parameters. Ensure proper permissions.${CL}" - exit 1 - fi + # Exit if kernel parameters are unavailable + if [[ "$per_user_maxkeys" -eq 0 || "$per_user_maxbytes" -eq 0 ]]; then + echo -e "${CROSS}${RD} Error: Unable to read kernel parameters. Ensure proper permissions.${CL}" + exit 1 + fi - # Fetch key usage for user ID 100000 (typical for containers) - used_lxc_keys=$(awk '/100000:/ {print $2}' /proc/key-users 2>/dev/null || echo 0) - used_lxc_bytes=$(awk '/100000:/ {split($5, a, "/"); print a[1]}' /proc/key-users 2>/dev/null || echo 0) + # Fetch key usage for user ID 100000 (typical for containers) + used_lxc_keys=$(awk '/100000:/ {print $2}' /proc/key-users 2>/dev/null || echo 0) + used_lxc_bytes=$(awk '/100000:/ {split($5, a, "/"); print a[1]}' /proc/key-users 2>/dev/null || echo 0) - # Calculate thresholds and suggested new limits - threshold_keys=$((per_user_maxkeys - 100)) - threshold_bytes=$((per_user_maxbytes - 1000)) - new_limit_keys=$((per_user_maxkeys * 2)) - new_limit_bytes=$((per_user_maxbytes * 2)) + # Calculate thresholds and suggested new limits + threshold_keys=$((per_user_maxkeys - 100)) + threshold_bytes=$((per_user_maxbytes - 1000)) + new_limit_keys=$((per_user_maxkeys * 2)) + new_limit_bytes=$((per_user_maxbytes * 2)) - # Check if key or byte usage is near limits - failure=0 - if [[ "$used_lxc_keys" -gt "$threshold_keys" ]]; then - echo -e "${CROSS}${RD} Warning: Key usage is near the limit (${used_lxc_keys}/${per_user_maxkeys}).${CL}" - echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxkeys=${new_limit_keys}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." - failure=1 - fi - if [[ "$used_lxc_bytes" -gt "$threshold_bytes" ]]; then - echo -e "${CROSS}${RD} Warning: Key byte usage is near the limit (${used_lxc_bytes}/${per_user_maxbytes}).${CL}" - echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxbytes=${new_limit_bytes}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." - failure=1 - fi + # Check if key or byte usage is near limits + failure=0 + if [[ "$used_lxc_keys" -gt "$threshold_keys" ]]; then + echo -e "${CROSS}${RD} Warning: Key usage is near the limit (${used_lxc_keys}/${per_user_maxkeys}).${CL}" + echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxkeys=${new_limit_keys}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." + failure=1 + fi + if [[ "$used_lxc_bytes" -gt "$threshold_bytes" ]]; then + echo -e "${CROSS}${RD} Warning: Key byte usage is near the limit (${used_lxc_bytes}/${per_user_maxbytes}).${CL}" + echo -e "${INFO} Suggested action: Set ${GN}kernel.keys.maxbytes=${new_limit_bytes}${CL} in ${BOLD}/etc/sysctl.d/98-community-scripts.conf${CL}." + failure=1 + fi - # Provide next steps if issues are detected - if [[ "$failure" -eq 1 ]]; then - echo -e "${INFO} To apply changes, run: ${BOLD}service procps force-reload${CL}" - exit 1 - fi + # Provide next steps if issues are detected + if [[ "$failure" -eq 1 ]]; then + echo -e "${INFO} To apply changes, run: ${BOLD}service procps force-reload${CL}" + exit 1 + fi - echo -e "${CM}${GN} All kernel key limits are within safe thresholds.${CL}" + echo -e "${CM}${GN} All kernel key limits are within safe thresholds.${CL}" } # This function checks the system architecture and exits if it's not "amd64". arch_check() { - if [ "$(dpkg --print-architecture)" != "amd64" ]; then - echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n" - echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n" - echo -e "Exiting..." - sleep 2 - exit - fi + if [ "$(dpkg --print-architecture)" != "amd64" ]; then + echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n" + echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n" + echo -e "Exiting..." + sleep 2 + exit + fi } # Function to get the current IP address based on the distribution get_current_ip() { - if [ -f /etc/os-release ]; then - # Check for Debian/Ubuntu (uses hostname -I) - if grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then - CURRENT_IP=$(hostname -I | awk '{print $1}') - # Check for Alpine (uses ip command) - elif grep -q 'ID=alpine' /etc/os-release; then - CURRENT_IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1) - else - CURRENT_IP="Unknown" - fi + if [ -f /etc/os-release ]; then + # Check for Debian/Ubuntu (uses hostname -I) + if grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then + CURRENT_IP=$(hostname -I | awk '{print $1}') + # Check for Alpine (uses ip command) + elif grep -q 'ID=alpine' /etc/os-release; then + CURRENT_IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1) + else + CURRENT_IP="Unknown" fi - echo "$CURRENT_IP" + fi + echo "$CURRENT_IP" } # Function to update the IP address in the MOTD file update_motd_ip() { - MOTD_FILE="/etc/motd" + MOTD_FILE="/etc/motd" - if [ -f "$MOTD_FILE" ]; then - # Remove existing IP Address lines to prevent duplication - sed -i '/IP Address:/d' "$MOTD_FILE" + if [ -f "$MOTD_FILE" ]; then + # Remove existing IP Address lines to prevent duplication + sed -i '/IP Address:/d' "$MOTD_FILE" - IP=$(get_current_ip) - # Add the new IP address - echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >>"$MOTD_FILE" - fi + IP=$(get_current_ip) + # Add the new IP address + echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >>"$MOTD_FILE" + fi } # Function to download & save header files get_header() { - local app_name=$(echo ${APP,,} | tr -d ' ') - local header_url="https://github.com/community-scripts/ProxmoxVED/raw/main/ct/headers/${app_name}" - local local_header_path="/usr/local/community-scripts/headers/${app_name}" + local app_name=$(echo ${APP,,} | tr -d ' ') + local header_url="https://github.com/community-scripts/ProxmoxVED/raw/main/ct/headers/${app_name}" + local local_header_path="/usr/local/community-scripts/headers/${app_name}" - mkdir -p "/usr/local/community-scripts/headers" + mkdir -p "/usr/local/community-scripts/headers" - # Check if local file already present - if [ ! -f "$local_header_path" ]; then - wget -qO "$local_header_path" "$header_url" - if [ $? -ne 0 ]; then - echo -e "${WARN}${BOLD}${YLW}Failed to download header for ${app_name}. No header will be displayed.${CL}" - return 1 - fi + # Check if local file already present + if [ ! -f "$local_header_path" ]; then + curl -fsSL "$header_url" -o "$local_header_path" + if [ $? -ne 0 ]; then + echo -e "${WARN}${BOLD}${YLW}Failed to download header for ${app_name}. No header will be displayed.${CL}" + return 1 fi - cat "$local_header_path" + fi + cat "$local_header_path" } # This function sets the APP-Name into an ASCII Header in Slant, figlet needed on proxmox main node. header_info() { - local app_name=$(echo ${APP,,} | tr -d ' ') - local header_content + local app_name=$(echo ${APP,,} | tr -d ' ') + local header_content - # Download & save Header-File locally - header_content=$(get_header "$app_name") - if [ $? -ne 0 ]; then - # Fallback: Doesn't show Header - return 0 - fi + # Download & save Header-File locally + header_content=$(get_header "$app_name") + if [ $? -ne 0 ]; then + # Fallback: Doesn't show Header + return 0 + fi - # Show ASCII-Header - term_width=$(tput cols 2>/dev/null || echo 120) - clear - echo "$header_content" + # Show ASCII-Header + term_width=$(tput cols 2>/dev/null || echo 120) + clear + echo "$header_content" } # This function checks if the script is running through SSH and prompts the user to confirm if they want to proceed or exit. ssh_check() { - if [ -n "${SSH_CLIENT:+x}" ]; then - if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's advisable to utilize the Proxmox shell rather than SSH, as there may be potential complications with variable retrieval. Proceed using SSH?" 10 72; then - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Proceed using SSH" "You've chosen to proceed using SSH. If any issues arise, please run the script in the Proxmox shell before creating a repository issue." 10 72 - else - clear - echo "Exiting due to SSH usage. Please consider using the Proxmox shell." - exit - fi + if [ -n "${SSH_CLIENT:+x}" ]; then + if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's advisable to utilize the Proxmox shell rather than SSH, as there may be potential complications with variable retrieval. Proceed using SSH?" 10 72; then + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Proceed using SSH" "You've chosen to proceed using SSH. If any issues arise, please run the script in the Proxmox shell before creating a repository issue." 10 72 + else + clear + echo "Exiting due to SSH usage. Please consider using the Proxmox shell." + exit fi + fi } base_settings() { - # Default Settings - CT_TYPE="1" - DISK_SIZE="4" - CORE_COUNT="1" - RAM_SIZE="1024" - VERBOSE="${1:-no}" - PW="" - CT_ID=$NEXTID - HN=$NSAPP - BRG="vmbr0" - NET="dhcp" - IPv6="dhcp" - IPv6GW="" - GATE="" - APT_CACHER="" - APT_CACHER_IP="" - DISABLEIP6="no" - MTU="" - SD="" - NS="" - MAC="" - VLAN="" - SSH="no" - SSH_AUTHORIZED_KEY="" - TAGS="community-script-dev;" - ENABLE_NFS="no" - ENABLE_CIFS="no" - ENABLE_FUSE="no" + # Default Settings + CT_TYPE="1" + DISK_SIZE="4" + CORE_COUNT="1" + RAM_SIZE="1024" + VERBOSE="${1:-no}" + PW="" + CT_ID=$NEXTID + HN=$NSAPP + BRG="vmbr0" + NET="dhcp" + IPv6="dhcp" + IPv6GW="" + GATE="" + APT_CACHER="" + APT_CACHER_IP="" + DISABLEIP6="no" + MTU="" + SD="" + NS="" + MAC="" + VLAN="" + SSH="no" + SSH_AUTHORIZED_KEY="" + TAGS="community-script-dev;" + ENABLE_NFS="no" + ENABLE_CIFS="no" + ENABLE_FUSE="no" - # Override default settings with variables from ct script - CT_TYPE=${var_unprivileged:-$CT_TYPE} - DISK_SIZE=${var_disk:-$DISK_SIZE} - CORE_COUNT=${var_cpu:-$CORE_COUNT} - RAM_SIZE=${var_ram:-$RAM_SIZE} - VERB=${var_verbose:-$VERBOSE} - TAGS="${TAGS}${var_tags:-}" - ENABLE_FUSE=${var_fuse:-$ENABLE_FUSE} + # Override default settings with variables from ct script + CT_TYPE=${var_unprivileged:-$CT_TYPE} + DISK_SIZE=${var_disk:-$DISK_SIZE} + CORE_COUNT=${var_cpu:-$CORE_COUNT} + RAM_SIZE=${var_ram:-$RAM_SIZE} + VERB=${var_verbose:-$VERBOSE} + TAGS="${TAGS}${var_tags:-}" + ENABLE_FUSE=${var_fuse:-$ENABLE_FUSE} - # Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts - if [ -z "$var_os" ]; then - var_os="debian" - fi - if [ -z "$var_version" ]; then - var_version="12" - fi + # Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts + if [ -z "$var_os" ]; then + var_os="debian" + fi + if [ -z "$var_version" ]; then + var_version="12" + fi } # This function displays the default values for various settings. echo_default() { - # Convert CT_TYPE to description - CT_TYPE_DESC="Unprivileged" - if [ "$CT_TYPE" -eq 0 ]; then - CT_TYPE_DESC="Privileged" - fi + # Convert CT_TYPE to description + CT_TYPE_DESC="Unprivileged" + if [ "$CT_TYPE" -eq 0 ]; then + CT_TYPE_DESC="Privileged" + fi - # Output the selected values with icons - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" - echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" - echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" - echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CT_ID}${CL}" - if [ "$VERB" == "yes" ]; then - echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}" - fi - echo -e "${CREATING}${BOLD}${BL}Creating a ${APP} LXC using the above default settings${CL}" - echo -e " " + # Output the selected values with icons + echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" + echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" + echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" + echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CT_ID}${CL}" + if [ "$VERB" == "yes" ]; then + echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}Enabled${CL}" + fi + echo -e "${CREATING}${BOLD}${BL}Creating a ${APP} LXC using the above default settings${CL}" + echo -e " " } # This function is called when the user decides to exit the script. It clears the screen and displays an exit message. exit_script() { - clear - echo -e "\n${CROSS}${RD}User exited script${CL}\n" - exit + clear + echo -e "\n${CROSS}${RD}User exited script${CL}\n" + exit } # This function allows the user to configure advanced settings for the script. advanced_settings() { - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Here is an instructional tip:" "To make a selection, use the Spacebar." 8 58 - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "Default is: ${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58 - if [ "$var_os" != "alpine" ]; then - var_default_os="${var_os}" - var_os="" - while [ -z "$var_os" ]; do - if [ "$var_default_os" == "debian" ]; then - if var_os=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ - "debian" "" ON \ - "ubuntu" "" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_os" ]; then - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" - fi - else - exit_script - fi - fi - if [ "$var_default_os" == "ubuntu" ]; then - if var_os=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ - "debian" "" OFF \ - "ubuntu" "" ON \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_os" ]; then - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" - fi - else - exit_script - fi - fi - done - fi - - if [ "$var_os" == "debian" ]; then - var_default_version="${var_version}" - var_version="" - while [ -z "$var_version" ]; do - if [ "$var_default_version" == "11" ]; then - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \ - "11" "Bullseye" ON \ - "12" "Bookworm" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - fi - if [ "$var_default_version" == "12" ]; then - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \ - "11" "Bullseye" OFF \ - "12" "Bookworm" ON \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - fi - done - fi - - if [ "$var_os" == "ubuntu" ]; then - var_default_version="${var_version}" - var_version="" - while [ -z "$var_version" ]; do - if [ "$var_default_version" == "20.04" ]; then - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ - "20.04" "Focal" ON \ - "22.04" "Jammy" OFF \ - "24.04" "Noble" OFF \ - "24.10" "Oracular" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - elif [ "$var_default_version" == "22.04" ]; then - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ - "20.04" "Focal" OFF \ - "22.04" "Jammy" ON \ - "24.04" "Noble" OFF \ - "24.10" "Oracular" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - elif [ "$var_default_version" == "24.04" ]; then - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ - "20.04" "Focal" OFF \ - "22.04" "Jammy" OFF \ - "24.04" "Noble" ON \ - "24.10" "Oracular" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - else - if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ - "20.04" "Focal" OFF \ - "22.04" "Jammy" OFF \ - "24.04" "Noble" OFF \ - "24.10" "Oracular" ON \ - 3>&1 1>&2 2>&3); then - if [ -n "$var_version" ]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - fi - else - exit_script - fi - fi - done - fi - # Setting Default Tag for Advanced Settings - TAGS="community-script-dev;${var_tags:-}" - CT_DEFAULT_TYPE="${CT_TYPE}" - CT_TYPE="" - while [ -z "$CT_TYPE" ]; do - if [ "$CT_DEFAULT_TYPE" == "1" ]; then - if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \ - "1" "Unprivileged" ON \ - "0" "Privileged" OFF \ - 3>&1 1>&2 2>&3); then - if [ -n "$CT_TYPE" ]; then - CT_TYPE_DESC="Unprivileged" - if [ "$CT_TYPE" -eq 0 ]; then - CT_TYPE_DESC="Privileged" - fi - echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" - fi - else - exit_script - fi + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Here is an instructional tip:" "To make a selection, use the Spacebar." 8 58 + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "Default is: ${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58 + if [ "$var_os" != "alpine" ]; then + var_default_os="${var_os}" + var_os="" + while [ -z "$var_os" ]; do + if [ "$var_default_os" == "debian" ]; then + if var_os=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ + "debian" "" ON \ + "ubuntu" "" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_os" ]; then + echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" + fi + else + exit_script fi - if [ "$CT_DEFAULT_TYPE" == "0" ]; then - if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \ - "1" "Unprivileged" OFF \ - "0" "Privileged" ON \ - 3>&1 1>&2 2>&3); then - if [ -n "$CT_TYPE" ]; then - CT_TYPE_DESC="Unprivileged" - if [ "$CT_TYPE" -eq 0 ]; then - CT_TYPE_DESC="Privileged" - fi - echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" - fi - else - exit_script - fi + fi + if [ "$var_default_os" == "ubuntu" ]; then + if var_os=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ + "debian" "" OFF \ + "ubuntu" "" ON \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_os" ]; then + echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" + fi + else + exit_script fi + fi done + fi - while true; do - if PW1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then - if [[ ! -z "$PW1" ]]; then - if [[ "$PW1" == *" "* ]]; then - whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58 - elif [ ${#PW1} -lt 5 ]; then - whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58 - else - if PW2=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then - if [[ "$PW1" == "$PW2" ]]; then - PW="-password $PW1" - echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}" - break - else - whiptail --msgbox "Passwords do not match. Please try again." 8 58 - fi - else - exit_script - fi - fi - else - PW1="Automatic Login" - PW="" - echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}" - break - fi + if [ "$var_os" == "debian" ]; then + var_default_version="${var_version}" + var_version="" + while [ -z "$var_version" ]; do + if [ "$var_default_version" == "11" ]; then + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \ + "11" "Bullseye" ON \ + "12" "Bookworm" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi else - exit_script + exit_script fi + fi + if [ "$var_default_version" == "12" ]; then + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \ + "11" "Bullseye" OFF \ + "12" "Bookworm" ON \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi + else + exit_script + fi + fi done + fi - if CT_ID=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 $NEXTID --title "CONTAINER ID" 3>&1 1>&2 2>&3); then - if [ -z "$CT_ID" ]; then - CT_ID="$NEXTID" - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" + if [ "$var_os" == "ubuntu" ]; then + var_default_version="${var_version}" + var_version="" + while [ -z "$var_version" ]; do + if [ "$var_default_version" == "20.04" ]; then + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ + "20.04" "Focal" ON \ + "22.04" "Jammy" OFF \ + "24.04" "Noble" OFF \ + "24.10" "Oracular" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi else - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" + exit_script fi - else - exit - fi - - if CT_NAME=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 $NSAPP --title "HOSTNAME" 3>&1 1>&2 2>&3); then - if [ -z "$CT_NAME" ]; then - HN="$NSAPP" + elif [ "$var_default_version" == "22.04" ]; then + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ + "20.04" "Focal" OFF \ + "22.04" "Jammy" ON \ + "24.04" "Noble" OFF \ + "24.10" "Oracular" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi else - HN=$(echo ${CT_NAME,,} | tr -d ' ') + exit_script fi - echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}" - else - exit_script - fi - - if DISK_SIZE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 $var_disk --title "DISK SIZE" 3>&1 1>&2 2>&3); then - if [ -z "$DISK_SIZE" ]; then - DISK_SIZE="$var_disk" - echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" + elif [ "$var_default_version" == "24.04" ]; then + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ + "20.04" "Focal" OFF \ + "22.04" "Jammy" OFF \ + "24.04" "Noble" ON \ + "24.10" "Oracular" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi else - if ! [[ $DISK_SIZE =~ $INTEGER ]]; then - echo -e "{INFO}${HOLD}${RD} DISK SIZE MUST BE AN INTEGER NUMBER!${CL}" - advanced_settings - fi - echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" + exit_script fi - else - exit_script - fi - - if CORE_COUNT=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 $var_cpu --title "CORE COUNT" 3>&1 1>&2 2>&3); then - if [ -z "$CORE_COUNT" ]; then - CORE_COUNT="$var_cpu" - echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}" + else + if var_version=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \ + "20.04" "Focal" OFF \ + "22.04" "Jammy" OFF \ + "24.04" "Noble" OFF \ + "24.10" "Oracular" ON \ + 3>&1 1>&2 2>&3); then + if [ -n "$var_version" ]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + fi else - echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}" - fi - else - exit_script - fi - - if RAM_SIZE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 $var_ram --title "RAM" 3>&1 1>&2 2>&3); then - if [ -z "$RAM_SIZE" ]; then - RAM_SIZE="$var_ram" - echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" - else - echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" - fi - else - exit_script - fi - - if BRG=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" 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 - NET=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Static IPv4 CIDR Address (/24)" 8 58 dhcp --title "IP ADDRESS" 3>&1 1>&2 2>&3) - exit_status=$? - if [ $exit_status -eq 0 ]; then - if [ "$NET" = "dhcp" ]; then - echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" - break - else - if [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then - echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" - break - else - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "$NET is an invalid IPv4 CIDR address. Please enter a valid IPv4 CIDR address or 'dhcp'" 8 58 - fi - fi - else - exit_script + exit_script fi + fi done + fi + # Setting Default Tag for Advanced Settings + TAGS="community-script-dev;${var_tags:-}" + CT_DEFAULT_TYPE="${CT_TYPE}" + CT_TYPE="" + while [ -z "$CT_TYPE" ]; do + if [ "$CT_DEFAULT_TYPE" == "1" ]; then + if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \ + "1" "Unprivileged" ON \ + "0" "Privileged" OFF \ + 3>&1 1>&2 2>&3); then + if [ -n "$CT_TYPE" ]; then + CT_TYPE_DESC="Unprivileged" + if [ "$CT_TYPE" -eq 0 ]; then + CT_TYPE_DESC="Privileged" + fi + echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" + fi + else + exit_script + fi + fi + if [ "$CT_DEFAULT_TYPE" == "0" ]; then + if CT_TYPE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \ + "1" "Unprivileged" OFF \ + "0" "Privileged" ON \ + 3>&1 1>&2 2>&3); then + if [ -n "$CT_TYPE" ]; then + CT_TYPE_DESC="Unprivileged" + if [ "$CT_TYPE" -eq 0 ]; then + CT_TYPE_DESC="Privileged" + fi + echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" + fi + else + exit_script + fi + fi + done - if [ "$NET" != "dhcp" ]; then - while true; do - GATE1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3) - if [ -z "$GATE1" ]; then - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58 - elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58 + while true; do + if PW1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then + if [[ ! -z "$PW1" ]]; then + if [[ "$PW1" == *" "* ]]; then + whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58 + elif [ ${#PW1} -lt 5 ]; then + whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58 + else + if PW2=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then + if [[ "$PW1" == "$PW2" ]]; then + PW="-password $PW1" + echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}" + break else - GATE=",gw=$GATE1" - echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}" - break + whiptail --msgbox "Passwords do not match. Please try again." 8 58 fi - done - else - GATE="" - echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}" - fi - - if [ "$var_os" == "alpine" ]; then - APT_CACHER="" - APT_CACHER_IP="" - else - if APT_CACHER_IP=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then - APT_CACHER="${APT_CACHER_IP:+yes}" - echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}" - else + else exit_script + fi fi - fi - - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "IPv6" --yesno "Disable IPv6?" 10 58); then - DISABLEIP6="yes" + else + PW1="Automatic Login" + PW="" + echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}" + break + fi else - DISABLEIP6="no" + exit_script fi - echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}$DISABLEIP6${CL}" + done - if MTU1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default [1500])" 8 58 --title "MTU SIZE" 3>&1 1>&2 2>&3); then - if [ -z $MTU1 ]; then - MTU1="Default" - MTU="" - else - MTU=",mtu=$MTU1" - fi - echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}" + if CT_ID=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 $NEXTID --title "CONTAINER ID" 3>&1 1>&2 2>&3); then + if [ -z "$CT_ID" ]; then + CT_ID="$NEXTID" + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" else - exit_script + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" fi + else + exit + fi - if SD=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Search Domain (leave blank for HOST)" 8 58 --title "DNS Search Domain" 3>&1 1>&2 2>&3); then - if [ -z $SD ]; then - SX=Host - SD="" - else - SX=$SD - SD="-searchdomain=$SD" - fi - echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SX${CL}" + if CT_NAME=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 $NSAPP --title "HOSTNAME" 3>&1 1>&2 2>&3); then + if [ -z "$CT_NAME" ]; then + HN="$NSAPP" else - exit_script + HN=$(echo ${CT_NAME,,} | tr -d ' ') fi + echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}" + else + exit_script + fi - if NX=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Server IP (leave blank for HOST)" 8 58 --title "DNS SERVER IP" 3>&1 1>&2 2>&3); then - if [ -z $NX ]; then - NX=Host - NS="" - else - NS="-nameserver=$NX" - fi - echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}" + if DISK_SIZE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 $var_disk --title "DISK SIZE" 3>&1 1>&2 2>&3); then + if [ -z "$DISK_SIZE" ]; then + DISK_SIZE="$var_disk" + echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" else - exit_script - fi - - if MAC1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a MAC Address(leave blank for generated MAC)" 8 58 --title "MAC ADDRESS" 3>&1 1>&2 2>&3); then - if [ -z $MAC1 ]; then - MAC1="Default" - MAC="" - else - MAC=",hwaddr=$MAC1" - echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}" - fi - else - exit_script - fi - - if VLAN1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for no VLAN)" 8 58 --title "VLAN" 3>&1 1>&2 2>&3); then - if [ -z $VLAN1 ]; then - VLAN1="Default" - VLAN="" - else - VLAN=",tag=$VLAN1" - fi - echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN1${CL}" - else - exit_script - fi - - if ADV_TAGS=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 ${TAGS} --title "Advanced Tags" 3>&1 1>&2 2>&3); then - if [ -n "${ADV_TAGS}" ]; then - ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]') - TAGS="${ADV_TAGS}" - else - TAGS=";" - fi - echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}" - else - exit_script - fi - - if [[ "$PW" == -password* ]]; then - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable Root SSH Access?" 10 58); then - SSH="yes" - else - SSH="no" - fi - echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" - else - SSH="no" - echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" - fi - - if [[ "${SSH}" == "yes" ]]; then - SSH_AUTHORIZED_KEY="$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "SSH Authorized key for root (leave empty for none)" 8 58 --title "SSH Key" 3>&1 1>&2 2>&3)" - - if [[ -z "${SSH_AUTHORIZED_KEY}" ]]; then - echo "Warning: No SSH key provided." - fi - else - SSH_AUTHORIZED_KEY="" - fi - - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE (Filesystem in Userspace) support in the container?" 10 58); then - ENABLE_FUSE="yes" - else - ENABLE_FUSE="no" - fi - echo -e "${FUSE}${BOLD}${DGN}FUSE (Filesystem in Userspace) Support: ${BGN}$ENABLE_FUSE${CL}" - - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then - VERB="yes" - else - VERB="no" - fi - echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERB${CL}" - - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then - echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}" - else - clear - header_info - echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}" + if ! [[ $DISK_SIZE =~ $INTEGER ]]; then + echo -e "{INFO}${HOLD}${RD} DISK SIZE MUST BE AN INTEGER NUMBER!${CL}" advanced_settings + fi + echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" fi + else + exit_script + fi + + if CORE_COUNT=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 $var_cpu --title "CORE COUNT" 3>&1 1>&2 2>&3); then + if [ -z "$CORE_COUNT" ]; then + CORE_COUNT="$var_cpu" + echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}" + else + echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}" + fi + else + exit_script + fi + + if RAM_SIZE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 $var_ram --title "RAM" 3>&1 1>&2 2>&3); then + if [ -z "$RAM_SIZE" ]; then + RAM_SIZE="$var_ram" + echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" + else + echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" + fi + else + exit_script + fi + + if BRG=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" 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 + NET=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Static IPv4 CIDR Address (/24)" 8 58 dhcp --title "IP ADDRESS" 3>&1 1>&2 2>&3) + exit_status=$? + if [ $exit_status -eq 0 ]; then + if [ "$NET" = "dhcp" ]; then + echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" + break + else + if [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then + echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" + break + else + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "$NET is an invalid IPv4 CIDR address. Please enter a valid IPv4 CIDR address or 'dhcp'" 8 58 + fi + fi + else + exit_script + fi + done + + if [ "$NET" != "dhcp" ]; then + while true; do + GATE1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3) + if [ -z "$GATE1" ]; then + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58 + elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58 + else + GATE=",gw=$GATE1" + echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}" + break + fi + done + else + GATE="" + echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}" + fi + + if [ "$var_os" == "alpine" ]; then + APT_CACHER="" + APT_CACHER_IP="" + else + if APT_CACHER_IP=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then + APT_CACHER="${APT_CACHER_IP:+yes}" + echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}" + else + exit_script + fi + fi + + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "IPv6" --yesno "Disable IPv6?" 10 58); then + DISABLEIP6="yes" + else + DISABLEIP6="no" + fi + echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}$DISABLEIP6${CL}" + + if MTU1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default [1500])" 8 58 --title "MTU SIZE" 3>&1 1>&2 2>&3); then + if [ -z $MTU1 ]; then + MTU1="Default" + MTU="" + else + MTU=",mtu=$MTU1" + fi + echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}" + else + exit_script + fi + + if SD=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Search Domain (leave blank for HOST)" 8 58 --title "DNS Search Domain" 3>&1 1>&2 2>&3); then + if [ -z $SD ]; then + SX=Host + SD="" + else + SX=$SD + SD="-searchdomain=$SD" + fi + echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SX${CL}" + else + exit_script + fi + + if NX=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a DNS Server IP (leave blank for HOST)" 8 58 --title "DNS SERVER IP" 3>&1 1>&2 2>&3); then + if [ -z $NX ]; then + NX=Host + NS="" + else + NS="-nameserver=$NX" + fi + echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}" + else + exit_script + fi + + if MAC1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a MAC Address(leave blank for generated MAC)" 8 58 --title "MAC ADDRESS" 3>&1 1>&2 2>&3); then + if [ -z $MAC1 ]; then + MAC1="Default" + MAC="" + else + MAC=",hwaddr=$MAC1" + echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}" + fi + else + exit_script + fi + + if VLAN1=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for no VLAN)" 8 58 --title "VLAN" 3>&1 1>&2 2>&3); then + if [ -z $VLAN1 ]; then + VLAN1="Default" + VLAN="" + else + VLAN=",tag=$VLAN1" + fi + echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN1${CL}" + else + exit_script + fi + + if ADV_TAGS=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 ${TAGS} --title "Advanced Tags" 3>&1 1>&2 2>&3); then + if [ -n "${ADV_TAGS}" ]; then + ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]') + TAGS="${ADV_TAGS}" + else + TAGS=";" + fi + echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}" + else + exit_script + fi + + if [[ "$PW" == -password* ]]; then + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable Root SSH Access?" 10 58); then + SSH="yes" + else + SSH="no" + fi + echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" + else + SSH="no" + echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" + fi + + if [[ "${SSH}" == "yes" ]]; then + SSH_AUTHORIZED_KEY="$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --inputbox "SSH Authorized key for root (leave empty for none)" 8 58 --title "SSH Key" 3>&1 1>&2 2>&3)" + + if [[ -z "${SSH_AUTHORIZED_KEY}" ]]; then + echo "Warning: No SSH key provided." + fi + else + SSH_AUTHORIZED_KEY="" + fi + + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "FUSE Support" --yesno "Enable FUSE (Filesystem in Userspace) support in the container?" 10 58); then + ENABLE_FUSE="yes" + else + ENABLE_FUSE="no" + fi + echo -e "${FUSE}${BOLD}${DGN}FUSE (Filesystem in Userspace) Support: ${BGN}$ENABLE_FUSE${CL}" + + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then + VERB="yes" + else + VERB="no" + fi + echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERB${CL}" + + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then + echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above advanced settings${CL}" + else + clear + header_info + echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}" + advanced_settings + fi } diagnostics_check() { - if ! [ -d "/usr/local/community-scripts" ]; then - mkdir -p /usr/local/community-scripts - fi + if ! [ -d "/usr/local/community-scripts" ]; then + mkdir -p /usr/local/community-scripts + fi - if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then - if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then - cat </usr/local/community-scripts/diagnostics + if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then + if (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then + cat </usr/local/community-scripts/diagnostics DIAGNOSTICS=yes #This file is used to store the diagnostics settings for the Community-Scripts API. @@ -876,9 +876,9 @@ DIAGNOSTICS=yes #"status" #If you have any concerns, please review the source code at /misc/build.func EOF - DIAGNOSTICS="yes" - else - cat </usr/local/community-scripts/diagnostics + DIAGNOSTICS="yes" + else + cat </usr/local/community-scripts/diagnostics DIAGNOSTICS=no #This file is used to store the diagnostics settings for the Community-Scripts API. @@ -903,547 +903,547 @@ DIAGNOSTICS=no #"status" #If you have any concerns, please review the source code at /misc/build.func EOF - DIAGNOSTICS="no" - fi - else - DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics) - + DIAGNOSTICS="no" fi + else + DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics) + + fi } config_file() { - whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58 + whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58 - CONFIG_FILE="/opt/community-scripts/.settings" + CONFIG_FILE="/opt/community-scripts/.settings" - if [[ -f "/opt/community-scripts/${NSAPP}.conf" ]]; then - CONFIG_FILE="/opt/community-scripts/${NSAPP}.conf" - fi + if [[ -f "/opt/community-scripts/${NSAPP}.conf" ]]; then + CONFIG_FILE="/opt/community-scripts/${NSAPP}.conf" + fi - if CONFIG_FILE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set absolute path to config file" 8 58 $CONFIG_FILE --title "CONFIG FILE" 3>&1 1>&2 2>&3); then - if [[ ! -f "$CONFIG_FILE" ]]; then - echo -e "${CROSS}${RD}Config file not found, exiting script!.${CL}" - exit - else - echo -e "${INFO}${BOLD}${DGN}Using config File: ${BGN}$CONFIG_FILE${CL}" - base_settings - source "$CONFIG_FILE" - fi - fi - - if [[ "$var_os" == "debian" ]]; then - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" - if [[ "$var_version" == "11" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - elif [[ "$var_version" == "12" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - else - msg_error "Unknown setting for var_version, should be 11 or 12, was ${var_version}" - exit - fi - elif [[ "$var_os" == "ubuntu" ]]; then - echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" - if [[ "$var_version" == "20.04" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - elif [[ "$var_version" == "22.04" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - elif [[ "$var_version" == "24.04" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - elif [[ "$var_version" == "24.10" ]]; then - echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" - else - msg_error "Unknown setting for var_version, should be 20.04, 22.04, 24.04 or 24.10, was ${var_version}" - exit - fi + if CONFIG_FILE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set absolute path to config file" 8 58 $CONFIG_FILE --title "CONFIG FILE" 3>&1 1>&2 2>&3); then + if [[ ! -f "$CONFIG_FILE" ]]; then + echo -e "${CROSS}${RD}Config file not found, exiting script!.${CL}" + exit else - msg_error "Unknown setting for var_os! should be debian or ubuntu, was ${var_os}" + echo -e "${INFO}${BOLD}${DGN}Using config File: ${BGN}$CONFIG_FILE${CL}" + base_settings + source "$CONFIG_FILE" + fi + fi + + if [[ "$var_os" == "debian" ]]; then + echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" + if [[ "$var_version" == "11" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + elif [[ "$var_version" == "12" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + else + msg_error "Unknown setting for var_version, should be 11 or 12, was ${var_version}" + exit + fi + elif [[ "$var_os" == "ubuntu" ]]; then + echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" + if [[ "$var_version" == "20.04" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + elif [[ "$var_version" == "22.04" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + elif [[ "$var_version" == "24.04" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + elif [[ "$var_version" == "24.10" ]]; then + echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" + else + msg_error "Unknown setting for var_version, should be 20.04, 22.04, 24.04 or 24.10, was ${var_version}" + exit + fi + else + msg_error "Unknown setting for var_os! should be debian or ubuntu, was ${var_os}" + exit + fi + + if [[ -n "$CT_ID" ]]; then + + if [[ "$CT_ID" =~ ^([0-9]{3,4})-([0-9]{3,4})$ ]]; then + MIN_ID=${BASH_REMATCH[1]} + MAX_ID=${BASH_REMATCH[2]} + + if ((MIN_ID >= MAX_ID)); then + msg_error "Invalid Container ID range. The first number must be smaller than the second number, was ${CT_ID}" exit - fi + fi - if [[ -n "$CT_ID" ]]; then + LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json | grep -oP '"vmid":\s*\K\d+') - if [[ "$CT_ID" =~ ^([0-9]{3,4})-([0-9]{3,4})$ ]]; then - MIN_ID=${BASH_REMATCH[1]} - MAX_ID=${BASH_REMATCH[2]} - - if ((MIN_ID >= MAX_ID)); then - msg_error "Invalid Container ID range. The first number must be smaller than the second number, was ${CT_ID}" - exit - fi - - LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json | grep -oP '"vmid":\s*\K\d+') - - for ((ID = MIN_ID; ID <= MAX_ID; ID++)); do - if ! grep -q "^$ID$" <<<"$LIST_OF_IDS"; then - CT_ID=$ID - break - fi - done - - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" - - elif [[ "$CT_ID" =~ ^[0-9]+$ ]]; then - - LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json | grep -oP '"vmid":\s*\K\d+') - if ! grep -q "^$CT_ID$" <<<"$LIST_OF_IDS"; then - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" - else - msg_error "Container ID $CT_ID already exists" - exit - fi - else - msg_error "Invalid Container ID format. Needs to be 0000-9999 or 0-9999, was ${CT_ID}" - exit + for ((ID = MIN_ID; ID <= MAX_ID; ID++)); do + if ! grep -q "^$ID$" <<<"$LIST_OF_IDS"; then + CT_ID=$ID + break fi - fi + done - if [[ "$CT_TYPE" -eq 0 ]]; then - CT_TYPE_DESC="Privileged" - elif [[ "$CT_TYPE" -eq 1 ]]; then - CT_TYPE_DESC="Unprivileged" - else - msg_error "Unknown setting for CT_TYPE, should be 1 or 0, was ${CT_TYPE}" + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" + + elif [[ "$CT_ID" =~ ^[0-9]+$ ]]; then + + LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json | grep -oP '"vmid":\s*\K\d+') + if ! grep -q "^$CT_ID$" <<<"$LIST_OF_IDS"; then + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" + else + msg_error "Container ID $CT_ID already exists" exit - fi - echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" - - if [[ ! -z "$PW" ]]; then - - if [[ "$PW" == *" "* ]]; then - msg_error "Password cannot be empty" - exit - elif [[ ${#PW} -lt 5 ]]; then - msg_error "Password must be at least 5 characters long" - exit - else - echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}" - fi - PW="-password $PW" + fi else - PW="" - echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}Automatic Login${CL}" + msg_error "Invalid Container ID format. Needs to be 0000-9999 or 0-9999, was ${CT_ID}" + exit fi - echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" + fi - if [[ ! -z "$HN" ]]; then - echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}" + if [[ "$CT_TYPE" -eq 0 ]]; then + CT_TYPE_DESC="Privileged" + elif [[ "$CT_TYPE" -eq 1 ]]; then + CT_TYPE_DESC="Unprivileged" + else + msg_error "Unknown setting for CT_TYPE, should be 1 or 0, was ${CT_TYPE}" + exit + fi + echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}" + + if [[ ! -z "$PW" ]]; then + + if [[ "$PW" == *" "* ]]; then + msg_error "Password cannot be empty" + exit + elif [[ ${#PW} -lt 5 ]]; then + msg_error "Password must be at least 5 characters long" + exit else - msg_error "Hostname cannot be empty" - exit + echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}" fi + PW="-password $PW" + else + PW="" + echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}Automatic Login${CL}" + fi + echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}" - if [[ ! -z "$DISK_SIZE" ]]; then - if [[ "$DISK_SIZE" =~ ^-?[0-9]+$ ]]; then - echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" - else - msg_error "DISK_SIZE must be an integer, was ${DISK_SIZE}" - exit - fi + if [[ ! -z "$HN" ]]; then + echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}" + else + msg_error "Hostname cannot be empty" + exit + fi + + if [[ ! -z "$DISK_SIZE" ]]; then + if [[ "$DISK_SIZE" =~ ^-?[0-9]+$ ]]; then + echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}" else - msg_error "DISK_SIZE cannot be empty" - exit + msg_error "DISK_SIZE must be an integer, was ${DISK_SIZE}" + exit fi + else + msg_error "DISK_SIZE cannot be empty" + exit + fi - if [[ ! -z "$CORE_COUNT" ]]; then - if [[ "$CORE_COUNT" =~ ^-?[0-9]+$ ]]; then - echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" - else - msg_error "CORE_COUNT must be an integer, was ${CORE_COUNT}" - exit - fi + if [[ ! -z "$CORE_COUNT" ]]; then + if [[ "$CORE_COUNT" =~ ^-?[0-9]+$ ]]; then + echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}" else - msg_error "CORE_COUNT cannot be empty" - exit + msg_error "CORE_COUNT must be an integer, was ${CORE_COUNT}" + exit fi + else + msg_error "CORE_COUNT cannot be empty" + exit + fi - if [[ ! -z "$RAM_SIZE" ]]; then - if [[ "$RAM_SIZE" =~ ^-?[0-9]+$ ]]; then - echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" - else - msg_error "RAM_SIZE must be an integer, was ${RAM_SIZE}" - exit - fi + if [[ ! -z "$RAM_SIZE" ]]; then + if [[ "$RAM_SIZE" =~ ^-?[0-9]+$ ]]; then + echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}" else - msg_error "RAM_SIZE cannot be empty" - exit + msg_error "RAM_SIZE must be an integer, was ${RAM_SIZE}" + exit fi + else + msg_error "RAM_SIZE cannot be empty" + exit + fi - if [[ ! -z "$BRG" ]]; then - if grep -q "^iface ${BRG}" /etc/network/interfaces; then - echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}" - else - msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces" - exit - fi + if [[ ! -z "$BRG" ]]; then + if grep -q "^iface ${BRG}" /etc/network/interfaces; then + echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}" else - msg_error "Bridge cannot be empty" - exit + msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces" + exit fi + else + msg_error "Bridge cannot be empty" + exit + fi - 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_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$' + 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_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$' - if [[ ! -z $NET ]]; then - if [ "$NET" == "dhcp" ]; then - echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}DHCP${CL}" - echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}" - elif - [[ "$NET" =~ $ip_cidr_regex ]] - then - echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" - else - msg_error "Invalid IP Address format. Needs to be 0.0.0.0/0, was ${NET}" - exit - fi - fi - if [ ! -z "$GATE" ]; then - if [[ "$GATE" =~ $ip_regex ]]; then - echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE${CL}" - GATE=",gw=$GATE" - else - msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was ${GATE}" - exit - fi + if [[ ! -z $NET ]]; then + if [ "$NET" == "dhcp" ]; then + echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}DHCP${CL}" + echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}" + elif + [[ "$NET" =~ $ip_cidr_regex ]] + then + echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}" else - msg_error "Gateway IP Address cannot be empty" - exit + msg_error "Invalid IP Address format. Needs to be 0.0.0.0/0, was ${NET}" + exit fi - - if [[ ! -z "$APT_CACHER_IP" ]]; then - if [[ "$APT_CACHER_IP" =~ $ip_regex ]]; then - APT_CACHER="yes" - echo -e "${NETWORK}${BOLD}${DGN}APT-CACHER IP Address: ${BGN}$APT_CACHER_IP${CL}" - else - msg_error "Invalid IP Address format for APT-Cacher. Needs to be 0.0.0.0, was ${APT_CACHER_IP}" - exit - fi - fi - - if [[ "$DISABLEIP6" == "yes" ]]; then - echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}Yes${CL}" - elif [[ "$DISABLEIP6" == "no" ]]; then - echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}No${CL}" + fi + if [ ! -z "$GATE" ]; then + if [[ "$GATE" =~ $ip_regex ]]; then + echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE${CL}" + GATE=",gw=$GATE" else - msg_error "Disable IPv6 needs to be 'yes' or 'no'" - exit + msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was ${GATE}" + exit fi + else + msg_error "Gateway IP Address cannot be empty" + exit + fi - if [[ ! -z "$MTU" ]]; then - if [[ "$MTU" =~ ^-?[0-9]+$ ]]; then - echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU${CL}" - MTU=",mtu=$MTU" - else - msg_error "MTU must be an integer, was ${MTU}" - exit - fi + if [[ ! -z "$APT_CACHER_IP" ]]; then + if [[ "$APT_CACHER_IP" =~ $ip_regex ]]; then + APT_CACHER="yes" + echo -e "${NETWORK}${BOLD}${DGN}APT-CACHER IP Address: ${BGN}$APT_CACHER_IP${CL}" else - MTU="" - echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}" - + msg_error "Invalid IP Address format for APT-Cacher. Needs to be 0.0.0.0, was ${APT_CACHER_IP}" + exit fi + fi - if [[ ! -z "$SD" ]]; then - echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SD${CL}" - SD="-searchdomain=$SD" + if [[ "$DISABLEIP6" == "yes" ]]; then + echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}Yes${CL}" + elif [[ "$DISABLEIP6" == "no" ]]; then + echo -e "${DISABLEIPV6}${BOLD}${DGN}Disable IPv6: ${BGN}No${CL}" + else + msg_error "Disable IPv6 needs to be 'yes' or 'no'" + exit + fi + + if [[ ! -z "$MTU" ]]; then + if [[ "$MTU" =~ ^-?[0-9]+$ ]]; then + echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU${CL}" + MTU=",mtu=$MTU" else - SD="" - echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}HOST${CL}" + msg_error "MTU must be an integer, was ${MTU}" + exit fi + else + MTU="" + echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}" - if [[ ! -z "$NS" ]]; then - if [[ "$NS" =~ $ip_regex ]]; then - echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NS${CL}" - NS="-nameserver=$NS" - else - msg_error "Invalid IP Address format for DNS Server. Needs to be 0.0.0.0, was ${NS}" - exit - fi + fi + + if [[ ! -z "$SD" ]]; then + echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SD${CL}" + SD="-searchdomain=$SD" + else + SD="" + echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}HOST${CL}" + fi + + if [[ ! -z "$NS" ]]; then + if [[ "$NS" =~ $ip_regex ]]; then + echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NS${CL}" + NS="-nameserver=$NS" else - NS="" - echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}HOST${CL}" + msg_error "Invalid IP Address format for DNS Server. Needs to be 0.0.0.0, was ${NS}" + exit fi + else + NS="" + echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}HOST${CL}" + fi - if [[ ! -z "$MAC" ]]; then - if [[ "$MAC" =~ ^([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$ ]]; then - echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}" - MAC=",hwaddr=$MAC" - else - msg_error "MAC Address must be in the format xx:xx:xx:xx:xx:xx, was ${MAC}" - exit - fi - fi - - if [[ ! -z "$VLAN" ]]; then - if [[ "$VLAN" =~ ^-?[0-9]+$ ]]; then - echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN${CL}" - VLAN=",tag=$VLAN" - else - msg_error "VLAN must be an integer, was ${VLAN}" - exit - fi - fi - - if [[ ! -z "$TAGS" ]]; then - echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}" - fi - - if [[ "$SSH" == "yes" ]]; then - echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" - if [[ ! -z "$SSH_AUTHORIZED_KEY" ]]; then - echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}********************${CL}" - else - echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}None${CL}" - fi - elif [[ "$SSH" == "no" ]]; then - echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" + if [[ ! -z "$MAC" ]]; then + if [[ "$MAC" =~ ^([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$ ]]; then + echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}" + MAC=",hwaddr=$MAC" else - msg_error "SSH needs to be 'yes' or 'no', was ${SSH}" - exit + msg_error "MAC Address must be in the format xx:xx:xx:xx:xx:xx, was ${MAC}" + exit fi + fi - if [[ "$VERB" == "yes" ]]; then - echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERB${CL}" - elif [[ "$VERB" == "no" ]]; then - echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}No${CL}" + if [[ ! -z "$VLAN" ]]; then + if [[ "$VLAN" =~ ^-?[0-9]+$ ]]; then + echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN${CL}" + VLAN=",tag=$VLAN" else - msg_error "Verbose Mode needs to be 'yes' or 'no', was ${VERB}" - exit + msg_error "VLAN must be an integer, was ${VLAN}" + exit fi + fi - if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS WITH CONFIG FILE COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then - echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above settings${CL}" + if [[ ! -z "$TAGS" ]]; then + echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}" + fi + + if [[ "$SSH" == "yes" ]]; then + echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" + if [[ ! -z "$SSH_AUTHORIZED_KEY" ]]; then + echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}********************${CL}" else - clear - header_info - echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}" - config_file + echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}None${CL}" fi + elif [[ "$SSH" == "no" ]]; then + echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}" + else + msg_error "SSH needs to be 'yes' or 'no', was ${SSH}" + exit + fi + + if [[ "$VERB" == "yes" ]]; then + echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERB${CL}" + elif [[ "$VERB" == "no" ]]; then + echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}No${CL}" + else + msg_error "Verbose Mode needs to be 'yes' or 'no', was ${VERB}" + exit + fi + + if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS WITH CONFIG FILE COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then + echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above settings${CL}" + else + clear + header_info + echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}" + config_file + fi } install_script() { - pve_check - shell_check - root_check - arch_check - ssh_check - maxkeys_check - diagnostics_check + pve_check + shell_check + root_check + arch_check + ssh_check + maxkeys_check + diagnostics_check - if systemctl is-active -q ping-instances.service; then - systemctl -q stop ping-instances.service + if systemctl is-active -q ping-instances.service; then + systemctl -q stop ping-instances.service + fi + NEXTID=$(pvesh get /cluster/nextid) + timezone=$(cat /etc/timezone) + header_info + while true; do + + CHOICE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \ + 18 60 6 \ + "1" "Default Settings" \ + "2" "Default Settings (with output)" \ + "3" "Advanced Settings" \ + "4" "Diagnostic Settings" \ + "5" "Use Config File" \ + "6" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3) + + if [ $? -ne 0 ]; then + echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}" + exit 0 fi - NEXTID=$(pvesh get /cluster/nextid) - timezone=$(cat /etc/timezone) - header_info - while true; do - CHOICE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \ - 18 60 6 \ - "1" "Default Settings" \ - "2" "Default Settings (with output)" \ - "3" "Advanced Settings" \ - "4" "Diagnostic Settings" \ - "5" "Use Config File" \ - "6" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3) - - if [ $? -ne 0 ]; then - echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}" - exit 0 + case $CHOICE in + 1) + header_info + echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}" + VERB="no" + METHOD="default" + base_settings "$VERB" + echo_default + break + ;; + 2) + header_info + echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}" + VERB="yes" + METHOD="default" + base_settings "$VERB" + echo_default + break + ;; + 3) + header_info + echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}" + METHOD="advanced" + base_settings + advanced_settings + break + ;; + 4) + if [[ $DIAGNOSTICS == "yes" ]]; then + if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ + --yes-button "No" --no-button "Back"; then + DIAGNOSTICS="no" + sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 fi + else + if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ + --yes-button "Yes" --no-button "Back"; then + DIAGNOSTICS="yes" + sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics + whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 + fi + fi - case $CHOICE in - 1) - header_info - echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}" - VERB="no" - METHOD="default" - base_settings "$VERB" - echo_default - break - ;; - 2) - header_info - echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}" - VERB="yes" - METHOD="default" - base_settings "$VERB" - echo_default - break - ;; - 3) - header_info - echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}" - METHOD="advanced" - base_settings - advanced_settings - break - ;; - 4) - if [[ $DIAGNOSTICS == "yes" ]]; then - if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ - --yes-button "No" --no-button "Back"; then - DIAGNOSTICS="no" - sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 - fi - else - if whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ - --yes-button "Yes" --no-button "Back"; then - DIAGNOSTICS="yes" - sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics - whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 - fi - fi - - ;; - 5) - header_info - echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}" - config_file - break - ;; - 6) - echo -e "${CROSS}${RD}Exiting.${CL}" - exit 0 - ;; - *) - echo -e "${CROSS}${RD}Invalid option, please try again.${CL}" - ;; - esac - done + ;; + 5) + header_info + echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}" + config_file + break + ;; + 6) + echo -e "${CROSS}${RD}Exiting.${CL}" + exit 0 + ;; + *) + echo -e "${CROSS}${RD}Invalid option, please try again.${CL}" + ;; + esac + done } check_container_resources() { - # Check actual RAM & Cores - current_ram=$(free -m | awk 'NR==2{print $2}') - current_cpu=$(nproc) + # Check actual RAM & Cores + current_ram=$(free -m | awk 'NR==2{print $2}') + current_cpu=$(nproc) - # Check whether the current RAM is less than the required RAM or the CPU cores are less than required - if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then - echo -e "\n${INFO}${HOLD} ${GN}Required: ${var_cpu} CPU, ${var_ram}MB RAM ${CL}| ${RD}Current: ${current_cpu} CPU, ${current_ram}MB RAM${CL}" - echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n" - echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? " - read -r prompt - # Check if the input is 'yes', otherwise exit with status 1 - if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then - echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}" - exit 1 - fi - else - echo -e "" + # Check whether the current RAM is less than the required RAM or the CPU cores are less than required + if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then + echo -e "\n${INFO}${HOLD} ${GN}Required: ${var_cpu} CPU, ${var_ram}MB RAM ${CL}| ${RD}Current: ${current_cpu} CPU, ${current_ram}MB RAM${CL}" + echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n" + echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? " + read -r prompt + # Check if the input is 'yes', otherwise exit with status 1 + if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then + echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}" + exit 1 fi + else + echo -e "" + fi } check_container_storage() { - # Check if the /boot partition is more than 80% full - total_size=$(df /boot --output=size | tail -n 1) - local used_size=$(df /boot --output=used | tail -n 1) - usage=$((100 * used_size / total_size)) - if ((usage > 80)); then - # Prompt the user for confirmation to continue - echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}" - echo -ne "Continue anyway? " - read -r prompt - # Check if the input is 'y' or 'yes', otherwise exit with status 1 - if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then - echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}" - exit 1 - fi + # Check if the /boot partition is more than 80% full + total_size=$(df /boot --output=size | tail -n 1) + local used_size=$(df /boot --output=used | tail -n 1) + usage=$((100 * used_size / total_size)) + if ((usage > 80)); then + # Prompt the user for confirmation to continue + echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}" + echo -ne "Continue anyway? " + read -r prompt + # Check if the input is 'y' or 'yes', otherwise exit with status 1 + if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then + echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}" + exit 1 fi + fi } start() { - LOGDIR="/usr/local/community-scripts/logs" - mkdir -p "$LOGDIR" + LOGDIR="/usr/local/community-scripts/logs" + mkdir -p "$LOGDIR" - if command -v pveversion >/dev/null 2>&1; then - if ! (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "${APP} LXC" --yesno "This will create a New ${APP} LXC. Proceed?" 10 58); then - clear - exit_script - exit - fi - SPINNER_PID="" - install_script + if command -v pveversion >/dev/null 2>&1; then + if ! (whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "${APP} LXC" --yesno "This will create a New ${APP} LXC. Proceed?" 10 58); then + clear + exit_script + exit fi + SPINNER_PID="" + install_script + fi - if ! command -v pveversion >/dev/null 2>&1; then - CHOICE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \ - "Support/Update functions for ${APP} LXC. Choose an option:" \ - 12 60 3 \ - "1" "YES (Silent Mode)" \ - "2" "YES (Verbose Mode)" \ - "3" "NO (Cancel Update)" --nocancel --default-item "1" 3>&1 1>&2 2>&3) + if ! command -v pveversion >/dev/null 2>&1; then + CHOICE=$(whiptail --backtitle "[dev] Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \ + "Support/Update functions for ${APP} LXC. Choose an option:" \ + 12 60 3 \ + "1" "YES (Silent Mode)" \ + "2" "YES (Verbose Mode)" \ + "3" "NO (Cancel Update)" --nocancel --default-item "1" 3>&1 1>&2 2>&3) - case "$CHOICE" in - 1) - VERB="no" - set_std_mode - log_message "INFO" "Update started (Silent Mode)" - ;; - 2) - VERB="yes" - set_std_mode - log_message "INFO" "Update started (Verbose Mode)" - ;; - 3) - clear - log_message "INFO" "Update aborted." - exit_script - exit - ;; - esac + case "$CHOICE" in + 1) + VERB="no" + set_std_mode + log_message "INFO" "Update started (Silent Mode)" + ;; + 2) + VERB="yes" + set_std_mode + log_message "INFO" "Update started (Verbose Mode)" + ;; + 3) + clear + log_message "INFO" "Update aborted." + exit_script + exit + ;; + esac - SPINNER_PID="" - update_script - fi + SPINNER_PID="" + update_script + fi } # This function collects user settings and integrates all the collected information. build_container() { - # if [ "$VERB" == "yes" ]; then set -x; fi + # if [ "$VERB" == "yes" ]; then set -x; fi - if [ "$CT_TYPE" == "1" ]; then - FEATURES="keyctl=1,nesting=1" - else - FEATURES="nesting=1" - fi + if [ "$CT_TYPE" == "1" ]; then + FEATURES="keyctl=1,nesting=1" + else + FEATURES="nesting=1" + fi - if [ "$ENABLE_FUSE" == "yes" ]; then - FEATURES+=",fuse=1" - fi + if [ "$ENABLE_FUSE" == "yes" ]; then + FEATURES+=",fuse=1" + fi - if [[ $DIAGNOSTICS == "yes" ]]; then - post_to_api - fi + if [[ $DIAGNOSTICS == "yes" ]]; then + post_to_api + fi - FEATURES="${FEATURES#,}" - TEMP_DIR=$(mktemp -d) - pushd $TEMP_DIR >/dev/null - if [ "$var_os" == "alpine" ]; then - export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/alpine-install.func)" - else - export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)" - fi - export RANDOM_UUID="$RANDOM_UUID" - export CACHER="$APT_CACHER" - export CACHER_IP="$APT_CACHER_IP" - export tz="$timezone" - export DISABLEIPV6="$DISABLEIP6" - export APPLICATION="$APP" - export app="$NSAPP" - export PASSWORD="$PW" - export VERBOSE="$VERB" - export SSH_ROOT="${SSH}" - export SSH_AUTHORIZED_KEY - export CTID="$CT_ID" - export CTTYPE="$CT_TYPE" - export PCT_OSTYPE="$var_os" - export PCT_OSVERSION="$var_version" - export PCT_DISK_SIZE="$DISK_SIZE" - export IPv6="$IPv6" - export PCT_OPTIONS=" + FEATURES="${FEATURES#,}" + TEMP_DIR=$(mktemp -d) + pushd $TEMP_DIR >/dev/null + if [ "$var_os" == "alpine" ]; then + export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/alpine-install.func)" + else + export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)" + fi + export RANDOM_UUID="$RANDOM_UUID" + export CACHER="$APT_CACHER" + export CACHER_IP="$APT_CACHER_IP" + export tz="$timezone" + export DISABLEIPV6="$DISABLEIP6" + export APPLICATION="$APP" + export app="$NSAPP" + export PASSWORD="$PW" + export VERBOSE="$VERB" + export SSH_ROOT="${SSH}" + export SSH_AUTHORIZED_KEY + export CTID="$CT_ID" + export CTTYPE="$CT_TYPE" + export PCT_OSTYPE="$var_os" + export PCT_OSVERSION="$var_version" + export PCT_DISK_SIZE="$DISK_SIZE" + export IPv6="$IPv6" + export PCT_OPTIONS=" -features $FEATURES -hostname $HN -tags $TAGS @@ -1457,12 +1457,12 @@ build_container() { $PW " - # This executes create_lxc.sh and creates the container and .conf file - bash -c "$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/create_lxc.sh)" || exit $? + # This executes create_lxc.sh and creates the container and .conf file + bash -c "$(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/ct/create_lxc.sh)" || exit $? - LXC_CONFIG=/etc/pve/lxc/${CTID}.conf - if [ "$CT_TYPE" == "0" ]; then - cat <>$LXC_CONFIG + LXC_CONFIG=/etc/pve/lxc/${CTID}.conf + if [ "$CT_TYPE" == "0" ]; then + cat <>$LXC_CONFIG # USB passthrough lxc.cgroup2.devices.allow: a lxc.cap.drop: @@ -1474,11 +1474,11 @@ lxc.mount.entry: /dev/ttyUSB1 dev/ttyUSB1 none bind,optional,create= lxc.mount.entry: /dev/ttyACM0 dev/ttyACM0 none bind,optional,create=file lxc.mount.entry: /dev/ttyACM1 dev/ttyACM1 none bind,optional,create=file EOF - fi + fi - if [ "$CT_TYPE" == "0" ]; then - if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" || "$APP" == "FileFlows" ]]; then - cat <>$LXC_CONFIG + if [ "$CT_TYPE" == "0" ]; then + if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" || "$APP" == "FileFlows" ]]; then + cat <>$LXC_CONFIG # VAAPI hardware transcoding lxc.cgroup2.devices.allow: c 226:0 rwm lxc.cgroup2.devices.allow: c 226:128 rwm @@ -1487,50 +1487,50 @@ lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file EOF - fi - else - if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" || "$APP" == "FileFlows" ]]; then - if [[ -e "/dev/dri/renderD128" ]]; then - if [[ -e "/dev/dri/card0" ]]; then - cat <>$LXC_CONFIG + fi + else + if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" || "$APP" == "FileFlows" ]]; then + if [[ -e "/dev/dri/renderD128" ]]; then + if [[ -e "/dev/dri/card0" ]]; then + cat <>$LXC_CONFIG # VAAPI hardware transcoding dev0: /dev/dri/card0,gid=44 dev1: /dev/dri/renderD128,gid=104 EOF - else - cat <>$LXC_CONFIG + else + cat <>$LXC_CONFIG # VAAPI hardware transcoding dev0: /dev/dri/card1,gid=44 dev1: /dev/dri/renderD128,gid=104 EOF - fi - fi fi + fi fi + fi - # This starts the container and executes -install.sh - msg_info "Starting LXC Container" - pct start "$CTID" - msg_ok "Started LXC Container" - if [ "$var_os" == "alpine" ]; then - sleep 3 - pct exec "$CTID" -- /bin/sh -c 'cat </etc/apk/repositories + # This starts the container and executes -install.sh + msg_info "Starting LXC Container" + pct start "$CTID" + msg_ok "Started LXC Container" + if [ "$var_os" == "alpine" ]; then + sleep 3 + pct exec "$CTID" -- /bin/sh -c 'cat </etc/apk/repositories http://dl-cdn.alpinelinux.org/alpine/latest-stable/main http://dl-cdn.alpinelinux.org/alpine/latest-stable/community EOF' - pct exec "$CTID" -- ash -c "apk add bash >/dev/null" - fi - lxc-attach -n "$CTID" -- bash -c "$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/$var_install.sh)" || exit $? + pct exec "$CTID" -- ash -c "apk add bash >/dev/null" + fi + lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/$var_install.sh)" || exit $? } # This function sets the description of the container. description() { - IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) + IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) - # Generate LXC Description - DESCRIPTION=$( - cat < Logo @@ -1558,38 +1558,38 @@ description() { EOF - ) + ) - # Set Description in LXC - pct set "$CTID" -description "$DESCRIPTION" + # Set Description in LXC + pct set "$CTID" -description "$DESCRIPTION" - if [[ -f /etc/systemd/system/ping-instances.service ]]; then - systemctl start ping-instances.service - fi + if [[ -f /etc/systemd/system/ping-instances.service ]]; then + systemctl start ping-instances.service + fi - post_update_to_api "done" "none" + post_update_to_api "done" "none" } set_std_mode() { - if [ "$VERB" = "yes" ]; then - STD="" - else - STD="silent" - fi + if [ "$VERB" = "yes" ]; then + STD="" + else + STD="silent" + fi } # Silent execution function silent() { - if [ "$VERB" = "no" ]; then - "$@" >>"$LOGFILE" 2>&1 - else - "$@" 2>&1 | tee -a "$LOGFILE" - fi + if [ "$VERB" = "no" ]; then + "$@" >>"$LOGFILE" 2>&1 + else + "$@" 2>&1 | tee -a "$LOGFILE" + fi } exit_script() { - exit_code=$? # Capture exit status - post_update_to_api "failed" "$exit_code" + exit_code=$? # Capture exit status + post_update_to_api "failed" "$exit_code" } trap 'exit_script' EXIT diff --git a/misc/install.func b/misc/install.func index d579147..915f8d9 100644 --- a/misc/install.func +++ b/misc/install.func @@ -6,198 +6,198 @@ # This function sets color variables for formatting output in the terminal color() { - # Colors - YW=$(echo "\033[33m") - YWB=$(echo "\033[93m") - BL=$(echo "\033[36m") - RD=$(echo "\033[01;31m") - GN=$(echo "\033[1;92m") + # Colors + YW=$(echo "\033[33m") + YWB=$(echo "\033[93m") + BL=$(echo "\033[36m") + RD=$(echo "\033[01;31m") + GN=$(echo "\033[1;92m") - # Formatting - CL=$(echo "\033[m") - BFR="\\r\\033[K" - BOLD=$(echo "\033[1m") - HOLD=" " - TAB=" " + # Formatting + CL=$(echo "\033[m") + BFR="\\r\\033[K" + BOLD=$(echo "\033[1m") + HOLD=" " + TAB=" " - # System - RETRY_NUM=10 - RETRY_EVERY=3 + # System + RETRY_NUM=10 + RETRY_EVERY=3 - # Icons - CM="${TAB}✔️${TAB}${CL}" - CROSS="${TAB}✖️${TAB}${CL}" - INFO="${TAB}💡${TAB}${CL}" - NETWORK="${TAB}📡${TAB}${CL}" - OS="${TAB}🖥️${TAB}${CL}" - OSVERSION="${TAB}🌟${TAB}${CL}" - HOSTNAME="${TAB}🏠${TAB}${CL}" - GATEWAY="${TAB}🌐${TAB}${CL}" - DEFAULT="${TAB}⚙️${TAB}${CL}" + # Icons + CM="${TAB}✔️${TAB}${CL}" + CROSS="${TAB}✖️${TAB}${CL}" + INFO="${TAB}💡${TAB}${CL}" + NETWORK="${TAB}📡${TAB}${CL}" + OS="${TAB}🖥️${TAB}${CL}" + OSVERSION="${TAB}🌟${TAB}${CL}" + HOSTNAME="${TAB}🏠${TAB}${CL}" + GATEWAY="${TAB}🌐${TAB}${CL}" + DEFAULT="${TAB}⚙️${TAB}${CL}" } # Function to set STD mode based on verbosity set_std_mode() { - if [ "$VERBOSE" = "yes" ]; then - STD="" - else - STD="silent" - fi + if [ "$VERBOSE" = "yes" ]; then + STD="" + else + STD="silent" + fi } # Silent execution function silent() { - "$@" >/dev/null 2>&1 + "$@" >/dev/null 2>&1 } # This function enables IPv6 if it's not disabled and sets verbose mode verb_ip6() { - set_std_mode # Set STD mode based on VERBOSE + set_std_mode # Set STD mode based on VERBOSE - if [ "$DISABLEIPV6" == "yes" ]; then - echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf - $STD sysctl -p - fi + if [ "$DISABLEIPV6" == "yes" ]; then + echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf + $STD sysctl -p + fi } # This function sets error handling options and defines the error_handler function to handle errors catch_errors() { - set -Eeuo pipefail - trap 'error_handler $LINENO "$BASH_COMMAND"' ERR + set -Eeuo pipefail + trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } # This function handles errors error_handler() { - source <(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi - printf "\e[?25h" - 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}" - echo -e "\n$error_message" - if [[ "$line_number" -eq 50 ]]; then - echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n" - post_update_to_api "failed" "No error message, script ran in silent mode" - else - post_update_to_api "failed" "${command}" - fi + source <(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi + printf "\e[?25h" + 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}" + echo -e "\n$error_message" + if [[ "$line_number" -eq 50 ]]; then + echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n" + post_update_to_api "failed" "No error message, script ran in silent mode" + else + post_update_to_api "failed" "${command}" + fi } # This function displays a spinner. spinner() { - local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') - local spin_i=0 - local interval=0.1 - printf "\e[?25l" + local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏') + local spin_i=0 + local interval=0.1 + printf "\e[?25l" - local color="${YWB}" + local color="${YWB}" - while true; do - printf "\r ${color}%s${CL}" "${frames[spin_i]}" - spin_i=$(((spin_i + 1) % ${#frames[@]})) - sleep "$interval" - done + while true; do + printf "\r ${color}%s${CL}" "${frames[spin_i]}" + spin_i=$(((spin_i + 1) % ${#frames[@]})) + sleep "$interval" + done } # This function displays an informational message with a yellow color. msg_info() { - local msg="$1" - echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}" - spinner & - SPINNER_PID=$! + local msg="$1" + echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}" + spinner & + SPINNER_PID=$! } # This function displays a success message with a green color. msg_ok() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi - printf "\e[?25h" - local msg="$1" - echo -e "${BFR}${CM}${GN}${msg}${CL}" + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi + printf "\e[?25h" + local msg="$1" + echo -e "${BFR}${CM}${GN}${msg}${CL}" } # This function displays a error message with a red color. msg_error() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi - printf "\e[?25h" - local msg="$1" - echo -e "${BFR}${CROSS}${RD}${msg}${CL}" + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi + printf "\e[?25h" + local msg="$1" + echo -e "${BFR}${CROSS}${RD}${msg}${CL}" } # This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection setting_up_container() { - msg_info "Setting up Container OS" - sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen - locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1) - echo "LANG=${locale_line}" >/etc/default/locale - locale-gen >/dev/null - export LANG=${locale_line} - echo $tz >/etc/timezone - ln -sf /usr/share/zoneinfo/$tz /etc/localtime - for ((i = RETRY_NUM; i > 0; i--)); do - if [ "$(hostname -I)" != "" ]; then - break - fi - echo 1>&2 -en "${CROSS}${RD} No Network! " - sleep $RETRY_EVERY - done - if [ "$(hostname -I)" = "" ]; then - echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}" - echo -e "${NETWORK}Check Network Settings" - exit 1 + msg_info "Setting up Container OS" + sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen + locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1) + echo "LANG=${locale_line}" >/etc/default/locale + locale-gen >/dev/null + export LANG=${locale_line} + echo $tz >/etc/timezone + ln -sf /usr/share/zoneinfo/$tz /etc/localtime + for ((i = RETRY_NUM; i > 0; i--)); do + if [ "$(hostname -I)" != "" ]; then + break fi - rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED - systemctl disable -q --now systemd-networkd-wait-online.service - msg_ok "Set up Container OS" - msg_ok "Network Connected: ${BL}$(hostname -I)" + echo 1>&2 -en "${CROSS}${RD} No Network! " + sleep $RETRY_EVERY + done + if [ "$(hostname -I)" = "" ]; then + echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}" + echo -e "${NETWORK}Check Network Settings" + exit 1 + fi + rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED + systemctl disable -q --now systemd-networkd-wait-online.service + msg_ok "Set up Container OS" + msg_ok "Network Connected: ${BL}$(hostname -I)" } # This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected network_check() { - set +e - trap - ERR - ipv4_connected=false - ipv6_connected=false - sleep 1 - # Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers. - if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then - msg_ok "IPv4 Internet Connected" - ipv4_connected=true + set +e + trap - ERR + ipv4_connected=false + ipv6_connected=false + sleep 1 + # Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers. + if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then + msg_ok "IPv4 Internet Connected" + ipv4_connected=true + else + msg_error "IPv4 Internet Not Connected" + fi + + # Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers. + if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then + msg_ok "IPv6 Internet Connected" + ipv6_connected=true + else + msg_error "IPv6 Internet Not Connected" + fi + + # If both IPv4 and IPv6 checks fail, prompt the user + if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then + read -r -p "No Internet detected,would you like to continue anyway? " prompt + if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then + echo -e "${INFO}${RD}Expect Issues Without Internet${CL}" else - msg_error "IPv4 Internet Not Connected" + echo -e "${NETWORK}Check Network Settings" + exit 1 fi + fi - # Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers. - if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then - msg_ok "IPv6 Internet Connected" - ipv6_connected=true - else - msg_error "IPv6 Internet Not Connected" - fi - - # If both IPv4 and IPv6 checks fail, prompt the user - if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then - read -r -p "No Internet detected,would you like to continue anyway? " prompt - if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then - echo -e "${INFO}${RD}Expect Issues Without Internet${CL}" - else - echo -e "${NETWORK}Check Network Settings" - exit 1 - fi - fi - - RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }') - if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to ${BL}$RESOLVEDIP${CL}"; fi - set -e - trap 'error_handler $LINENO "$BASH_COMMAND"' ERR + RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }') + if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to ${BL}$RESOLVEDIP${CL}"; fi + set -e + trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } # This function updates the Container OS by running apt-get update and upgrade update_os() { - msg_info "Updating Container OS" - if [[ "$CACHER" == "yes" ]]; then - echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" >/etc/apt/apt.conf.d/00aptproxy - cat </usr/local/bin/apt-proxy-detect.sh + msg_info "Updating Container OS" + if [[ "$CACHER" == "yes" ]]; then + echo "Acquire::http::Proxy-Auto-Detect \"/usr/local/bin/apt-proxy-detect.sh\";" >/etc/apt/apt.conf.d/00aptproxy + cat </usr/local/bin/apt-proxy-detect.sh #!/bin/bash if nc -w1 -z "${CACHER_IP}" 3142; then echo -n "http://${CACHER_IP}:3142" @@ -205,71 +205,71 @@ else echo -n "DIRECT" fi EOF - chmod +x /usr/local/bin/apt-proxy-detect.sh - fi - $STD apt-get update - $STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade - rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED - msg_ok "Updated Container OS" + chmod +x /usr/local/bin/apt-proxy-detect.sh + fi + $STD apt-get update + $STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade + rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED + msg_ok "Updated Container OS" - msg_info "Installing core dependencies" - $STD apt-get update - $STD apt-get install -y sudo curl mc - msg_ok "Core dependencies installed" + msg_info "Installing core dependencies" + $STD apt-get update + $STD apt-get install -y sudo curl mc + msg_ok "Core dependencies installed" } # This function modifies the message of the day (motd) and SSH settings motd_ssh() { - grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc + grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc - if [ -f "/etc/os-release" ]; then - OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"') - OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"') - elif [ -f "/etc/debian_version" ]; then - OS_NAME="Debian" - OS_VERSION=$(cat /etc/debian_version) - fi + if [ -f "/etc/os-release" ]; then + OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"') + OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"') + elif [ -f "/etc/debian_version" ]; then + OS_NAME="Debian" + OS_VERSION=$(cat /etc/debian_version) + fi - PROFILE_FILE="/etc/profile.d/00_lxc-details.sh" - echo "echo -e \"\"" >"$PROFILE_FILE" - echo -e "echo -e \"${BOLD}${YW}${APPLICATION} LXC Container - DEV Repository${CL}\"" >>"$PROFILE_FILE" - echo -e "echo -e \"${RD}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL}\"" >>"$PROFILE_FILE" - echo -e "echo -e \"${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE" - echo -e "echo -e \"${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE" - echo -e "echo -e \"${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE" - echo -e "echo -e \"${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}\"" >>"$PROFILE_FILE" - echo "echo \"\"" >>"$PROFILE_FILE" + PROFILE_FILE="/etc/profile.d/00_lxc-details.sh" + echo "echo -e \"\"" >"$PROFILE_FILE" + echo -e "echo -e \"${BOLD}${YW}${APPLICATION} LXC Container - DEV Repository${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${RD}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${YW} Repository: ${GN}https://github.com/community-scripts/ProxmoxVED${CL}\"" >>"$PROFILE_FILE" + echo "echo \"\"" >>"$PROFILE_FILE" - chmod -x /etc/update-motd.d/* + chmod -x /etc/update-motd.d/* - if [[ "${SSH_ROOT}" == "yes" ]]; then - sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config - systemctl restart sshd - fi + if [[ "${SSH_ROOT}" == "yes" ]]; then + sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config + systemctl restart sshd + fi } # This function customizes the container by modifying the getty service and enabling auto-login for the root user customize() { - if [[ "$PASSWORD" == "" ]]; then - msg_info "Customizing Container" - GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf" - mkdir -p $(dirname $GETTY_OVERRIDE) - cat <$GETTY_OVERRIDE + if [[ "$PASSWORD" == "" ]]; then + msg_info "Customizing Container" + GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf" + mkdir -p $(dirname $GETTY_OVERRIDE) + cat <$GETTY_OVERRIDE [Service] ExecStart= ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM EOF - systemctl daemon-reload - systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//') - msg_ok "Customized Container" - fi - echo "bash -c \"\$(wget -qLO - https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update - chmod +x /usr/bin/update - - if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then - mkdir -p /root/.ssh - echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys - chmod 700 /root/.ssh - chmod 600 /root/.ssh/authorized_keys - fi + systemctl daemon-reload + systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//') + msg_ok "Customized Container" + fi + echo "bash -c \"\$(curl -fsSL https://github.com/community-scripts/ProxmoxVED/raw/main/ct/${app}.sh)\"" >/usr/bin/update + chmod +x /usr/bin/update + curl -fsSL + if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then + mkdir -p /root/.ssh + echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys + chmod 700 /root/.ssh + chmod 600 /root/.ssh/authorized_keys + fi } diff --git a/scripts/tools/filebrowser.sh b/scripts/tools/filebrowser.sh index 711a576..29015d3 100644 --- a/scripts/tools/filebrowser.sh +++ b/scripts/tools/filebrowser.sh @@ -5,8 +5,8 @@ # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE function header_info { - clear - cat <<"EOF" + clear + cat <<"EOF" _______ __ ____ / ____(_) /__ / __ )_________ _ __________ _____ / /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/ @@ -36,67 +36,66 @@ IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n [[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}') [[ -z "$IP" ]] && IP="127.0.0.1" - # Detect OS if [[ -f "/etc/alpine-release" ]]; then - OS="Alpine" - SERVICE_PATH="/etc/init.d/filebrowser" - PKG_MANAGER="apk add --no-cache" + OS="Alpine" + SERVICE_PATH="/etc/init.d/filebrowser" + PKG_MANAGER="apk add --no-cache" elif [[ -f "/etc/debian_version" ]]; then - OS="Debian" - SERVICE_PATH="/etc/systemd/system/filebrowser.service" - PKG_MANAGER="apt-get install -y" + OS="Debian" + SERVICE_PATH="/etc/systemd/system/filebrowser.service" + PKG_MANAGER="apt-get install -y" else - echo -e "${CROSS} Unsupported OS detected. Exiting." - exit 1 + echo -e "${CROSS} Unsupported OS detected. Exiting." + exit 1 fi header_info function msg_info() { - local msg="$1" - echo -e "${INFO} ${YW}${msg}...${CL}" + local msg="$1" + echo -e "${INFO} ${YW}${msg}...${CL}" } function msg_ok() { - local msg="$1" - echo -e "${CM} ${GN}${msg}${CL}" + local msg="$1" + echo -e "${CM} ${GN}${msg}${CL}" } function msg_error() { - local msg="$1" - echo -e "${CROSS} ${RD}${msg}${CL}" + local msg="$1" + echo -e "${CROSS} ${RD}${msg}${CL}" } if [ -f "$INSTALL_PATH" ]; then - echo -e "${YW}⚠️ ${APP} is already installed.${CL}" - read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt - if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then - msg_info "Uninstalling ${APP}" - if [[ "$OS" == "Debian" ]]; then - systemctl disable --now filebrowser.service &>/dev/null - rm -f "$SERVICE_PATH" - else - rc-service filebrowser stop &>/dev/null - rc-update del filebrowser &>/dev/null - rm -f "$SERVICE_PATH" - fi - rm -f "$INSTALL_PATH" "$DB_PATH" - msg_ok "${APP} has been uninstalled." - exit 0 - fi - - read -r -p "Would you like to update ${APP}? (y/N): " update_prompt - if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then - msg_info "Updating ${APP}" - wget -qO- https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null - chmod +x "$INSTALL_PATH" - msg_ok "Updated ${APP}" - exit 0 + echo -e "${YW}⚠️ ${APP} is already installed.${CL}" + read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt + if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then + msg_info "Uninstalling ${APP}" + if [[ "$OS" == "Debian" ]]; then + systemctl disable --now filebrowser.service &>/dev/null + rm -f "$SERVICE_PATH" else - echo -e "${YW}⚠️ Update skipped. Exiting.${CL}" - exit 0 + rc-service filebrowser stop &>/dev/null + rc-update del filebrowser &>/dev/null + rm -f "$SERVICE_PATH" fi + rm -f "$INSTALL_PATH" "$DB_PATH" + msg_ok "${APP} has been uninstalled." + exit 0 + fi + + read -r -p "Would you like to update ${APP}? (y/N): " update_prompt + if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then + msg_info "Updating ${APP}" + curl -fsSL https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null + chmod +x "$INSTALL_PATH" + msg_ok "Updated ${APP}" + exit 0 + else + echo -e "${YW}⚠️ Update skipped. Exiting.${CL}" + exit 0 + fi fi echo -e "${YW}⚠️ ${APP} is not installed.${CL}" @@ -105,43 +104,43 @@ PORT=${PORT:-$DEFAULT_PORT} read -r -p "Would you like to install ${APP}? (y/n): " install_prompt if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then - msg_info "Installing ${APP} on ${OS}" - $PKG_MANAGER wget tar curl &>/dev/null - wget -qO- https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null - chmod +x "$INSTALL_PATH" - msg_ok "Installed ${APP}" + msg_info "Installing ${APP} on ${OS}" + $PKG_MANAGER wget tar curl &>/dev/null + curl -fsSL https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null + chmod +x "$INSTALL_PATH" + msg_ok "Installed ${APP}" - msg_info "Creating FileBrowser directory" - mkdir -p /usr/local/community-scripts - chown root:root /usr/local/community-scripts - chmod 755 /usr/local/community-scripts - touch "$DB_PATH" - chown root:root "$DB_PATH" - chmod 644 "$DB_PATH" - msg_ok "Directory created successfully" + msg_info "Creating FileBrowser directory" + mkdir -p /usr/local/community-scripts + chown root:root /usr/local/community-scripts + chmod 755 /usr/local/community-scripts + touch "$DB_PATH" + chown root:root "$DB_PATH" + chmod 644 "$DB_PATH" + msg_ok "Directory created successfully" - read -r -p "Would you like to use No Authentication? (y/N): " auth_prompt - if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then - msg_info "Configuring No Authentication" - cd /usr/local/community-scripts - filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null - filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null - filebrowser config init --auth.method=noauth &>/dev/null - filebrowser config set --auth.method=noauth &>/dev/null - filebrowser users add ID 1 --perm.admin &>/dev/null - msg_ok "No Authentication configured" - else - msg_info "Setting up default authentication" - cd /usr/local/community-scripts - filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null - filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null - filebrowser users add admin helper-scripts.com --perm.admin --database "$DB_PATH" &>/dev/null - msg_ok "Default authentication configured (admin:helper-scripts.com)" - fi + read -r -p "Would you like to use No Authentication? (y/N): " auth_prompt + if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then + msg_info "Configuring No Authentication" + cd /usr/local/community-scripts + filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null + filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null + filebrowser config init --auth.method=noauth &>/dev/null + filebrowser config set --auth.method=noauth &>/dev/null + filebrowser users add ID 1 --perm.admin &>/dev/null + msg_ok "No Authentication configured" + else + msg_info "Setting up default authentication" + cd /usr/local/community-scripts + filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null + filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null + filebrowser users add admin helper-scripts.com --perm.admin --database "$DB_PATH" &>/dev/null + msg_ok "Default authentication configured (admin:helper-scripts.com)" + fi - msg_info "Creating service" - if [[ "$OS" == "Debian" ]]; then - cat < "$SERVICE_PATH" + msg_info "Creating service" + if [[ "$OS" == "Debian" ]]; then + cat <"$SERVICE_PATH" [Unit] Description=Filebrowser After=network-online.target @@ -157,9 +156,9 @@ Restart=always [Install] WantedBy=multi-user.target EOF - systemctl enable -q --now filebrowser - else - cat < "$SERVICE_PATH" + systemctl enable -q --now filebrowser + else + cat <"$SERVICE_PATH" #!/sbin/openrc-run command="/usr/local/bin/filebrowser" @@ -172,14 +171,14 @@ depend() { need net } EOF - chmod +x "$SERVICE_PATH" - rc-update add filebrowser default &>/dev/null - rc-service filebrowser start &>/dev/null - fi - msg_ok "Service created successfully" + chmod +x "$SERVICE_PATH" + rc-update add filebrowser default &>/dev/null + rc-service filebrowser start &>/dev/null + fi + msg_ok "Service created successfully" - echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}" + echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}" else - echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}" - exit 0 + echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}" + exit 0 fi diff --git a/scripts/tools/frigate-support.sh b/scripts/tools/frigate-support.sh index d118942..2c374ed 100644 --- a/scripts/tools/frigate-support.sh +++ b/scripts/tools/frigate-support.sh @@ -6,8 +6,8 @@ # https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE function header_info { - clear -cat <<"EOF" + clear + cat <<"EOF" ____ _ __ ____ __ / __/___(_)__ ____ _/ /____ / __/_ _____ ___ ___ ____/ /_ / _// __/ / _ `/ _ `/ __/ -_) _\ \/ // / _ \/ _ \/ _ \/ __/ __/ @@ -28,11 +28,11 @@ header_info # The array of device types # CHAR_DEVS+=(major:minor) -CHAR_DEVS+=("1:1") # mem -CHAR_DEVS+=("29:0") # fb0 -CHAR_DEVS+=("188:.*") # ttyUSB* -CHAR_DEVS+=("189:.*") # bus/usb/* -CHAR_DEVS+=("226:0") # card0 +CHAR_DEVS+=("1:1") # mem +CHAR_DEVS+=("29:0") # fb0 +CHAR_DEVS+=("188:.*") # ttyUSB* +CHAR_DEVS+=("189:.*") # bus/usb/* +CHAR_DEVS+=("226:0") # card0 CHAR_DEVS+=("226:128") # renderD128 # Proccess char device string @@ -89,5 +89,5 @@ EOF echo -e "\e[1;33m \nFinished....Reboot ${CTID} LXC to apply the changes.\n \e[0m" # In the Proxmox web shell run -# bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVED/raw/main/misc/frigate-support.sh)" -# Reboot the LXC to apply the changes \ No newline at end of file +# bash -c "$(curl -fsSL - https://github.com/community-scripts/ProxmoxVED/raw/main/misc/frigate-support.sh)" +# Reboot the LXC to apply the changes diff --git a/scripts/tools/hw-acceleration.sh b/scripts/tools/hw-acceleration.sh index 8122d1d..400868d 100644 --- a/scripts/tools/hw-acceleration.sh +++ b/scripts/tools/hw-acceleration.sh @@ -5,7 +5,7 @@ # License: MIT # https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE # Execute within the Proxmox shell -# bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVED/raw/main/misc/hw-acceleration.sh)" +# bash -c "$(curl -fsSL - https://github.com/community-scripts/ProxmoxVED/raw/main/misc/hw-acceleration.sh)" set -e function header_info { @@ -56,8 +56,8 @@ MSG_MAX_LENGTH=0 privileged_containers=$(pct list | awk 'NR>1 && system("grep -q \047unprivileged: 1\047 /etc/pve/lxc/" $1 ".conf")') if [ -z "$privileged_containers" ]; then - whiptail --msgbox "No Privileged Containers Found." 10 58 - exit + whiptail --msgbox "No Privileged Containers Found." 10 58 + exit fi while read -r TAG ITEM; do @@ -69,11 +69,11 @@ done < <(echo "$privileged_containers") privileged_container=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Privileged Containers on $NODE" --checklist "\nSelect a Container To Add Intel HW Acceleration:\n" 16 $((MSG_MAX_LENGTH + 23)) 6 "${PREV_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"') || exit header_info read -r -p "Verbose mode? " prompt - if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then +if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then STD="" - else +else STD="silent" - fi +fi header_info cat <>/etc/pve/lxc/${privileged_container}.conf diff --git a/scripts/vms/debian-vm-test-helper.sh b/scripts/vms/debian-vm-test-helper.sh index fd7858f..77211c6 100644 --- a/scripts/vms/debian-vm-test-helper.sh +++ b/scripts/vms/debian-vm-test-helper.sh @@ -4,8 +4,8 @@ # Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE -source /dev/stdin <<< $(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) -source /dev/stdin <<< $(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/helpers.func) +source /dev/stdin <<< $(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) +source /dev/stdin <<< $(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/helpers.func) function header_info { clear @@ -323,7 +323,7 @@ msg_info "Retrieving the URL for the Debian 12 Qcow2 Disk Image" URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2 sleep 2 msg_ok "${CL}${BL}${URL}${CL}" -wget -q --show-progress $URL +curl -fL --progress-bar "$URL" -O echo -en "\e[1A\e[0K" FILE=$(basename $URL) msg_ok "Downloaded ${CL}${BL}${FILE}${CL}" diff --git a/scripts/vms/debian-vm.sh b/scripts/vms/debian-vm.sh index 533d39f..9ea45f7 100644 --- a/scripts/vms/debian-vm.sh +++ b/scripts/vms/debian-vm.sh @@ -4,7 +4,7 @@ # Author: MickLesk (CanbiZ) # License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE -source /dev/stdin <<< $(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) +source /dev/stdin <<<$(curl -fsSL - https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/api.func) function header_info { clear @@ -63,7 +63,7 @@ THIN="discard=on,ssd=1," set -e trap 'error_handler $LINENO "$BASH_COMMAND"' ERR trap cleanup EXIT -trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT +trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM function error_handler() { local exit_code="$?" @@ -93,7 +93,7 @@ pushd $TEMP_DIR >/dev/null if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 12 VM" --yesno "This will create a New Debian 12 VM. Proceed?" 10 58; then : else - header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit + header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit fi function msg_info() { @@ -122,7 +122,7 @@ function check_root() { } function pve_check() { - if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then + if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported" echo -e "Requires Proxmox Virtual Environment Version 8.1 or later." echo -e "Exiting..." @@ -227,7 +227,7 @@ function advanced_settings() { 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 @@ -425,7 +425,7 @@ msg_info "Retrieving the URL for the Debian 12 Qcow2 Disk Image" URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2 sleep 2 msg_ok "${CL}${BL}${URL}${CL}" -wget -q --show-progress $URL +curl -fL --progress-bar "$URL" -O echo -en "\e[1A\e[0K" FILE=$(basename $URL) msg_ok "Downloaded ${CL}${BL}${FILE}${CL}" @@ -476,7 +476,7 @@ DESCRIPTION=$( spend Coffee

- + GitHub @@ -494,12 +494,12 @@ EOF ) qm set "$VMID" -description "$DESCRIPTION" >/dev/null if [ -n "$DISK_SIZE" ]; then - msg_info "Resizing disk to $DISK_SIZE GB" - qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null + msg_info "Resizing disk to $DISK_SIZE GB" + qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null else - msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB" - qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null -fi + msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB" + qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null +fi msg_ok "Created a Debian 12 VM ${CL}${BL}(${HN})" if [ "$START_VM" == "yes" ]; then