diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..841e80bc0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,38 @@
+# ---------------------------------------
+# Treat Shell files as first-class code
+# ---------------------------------------
+*.sh linguist-detectable=true
+*.bash linguist-language=Shell
+*.func linguist-language=Shell
+*.install linguist-language=Shell
+
+# ---------------------------------------
+# Treat Golang files as Go (for /api/)
+api/**/*.go linguist-language=Go
+
+# ---------------------------------------
+# Treat frontend as JavaScript/TypeScript (optional)
+frontend/**/*.ts linguist-language=TypeScript
+frontend/**/*.js linguist-language=JavaScript
+
+# ---------------------------------------
+# Exclude documentation from stats
+*.md linguist-documentation
+docs/** linguist-documentation
+README.md linguist-documentation
+CONTRIBUTING.md linguist-documentation
+SECURITY.md linguist-documentation
+
+# ---------------------------------------
+# Exclude generated/config files
+*.json linguist-generated
+frontend/public/json/*.json linguist-generated=false
+*.lock linguist-generated
+*.yml linguist-generated
+*.yaml linguist-generated
+.github/** linguist-generated
+.vscode/** linguist-generated
+
+# ---------------------------------------
+# Standard text handling
+* text=auto eol=lf
diff --git a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md
index d334b0c07..8507c7c2d 100644
--- a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md
+++ b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md
@@ -65,7 +65,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/
Example:
```bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
@@ -266,7 +266,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh
index 075fc694b..cf9333c4f 100644
--- a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh
+++ b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
@@ -9,7 +9,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/
APP="[APP_NAME]"
# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole"
var_tags="[TAGS]"
-# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
+# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
var_cpu="[CPU]"
# Number of cores (1-X) (e.g. 4) - default are 2
var_ram="[RAM]"
@@ -80,7 +80,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:[PORT]${CL}"
diff --git a/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md b/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md
index 376956d2f..8e23af37f 100644
--- a/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md
+++ b/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md
@@ -57,7 +57,7 @@
Example:
```bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
diff --git a/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh b/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh
index 01d725dd7..eb573fa32 100644
--- a/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh
+++ b/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index b1a6ee56f..1425c8037 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -37,3 +37,14 @@ Link: #
## π Additional Information (optional)
+
+---
+
+## π¦ Application Requirements (for new scripts)
+
+> Required for **π New script** submissions.
+> PRs that do not meet these requirements may be closed without review.
+- [ ] The application is **at least 6 months old**
+- [ ] The application is **actively maintained**
+- [ ] The application has **600+ GitHub stars**
+- [ ] Official **release tarballs** are published
diff --git a/.github/workflows/auto-update-app-headers.yml b/.github/workflows/auto-update-app-headers.yml.bak
similarity index 100%
rename from .github/workflows/auto-update-app-headers.yml
rename to .github/workflows/auto-update-app-headers.yml.bak
diff --git a/.github/workflows/move-to-main-repo.yaml b/.github/workflows/move-to-main-repo.yaml
index e22161dfc..bcc697b5f 100644
--- a/.github/workflows/move-to-main-repo.yaml
+++ b/.github/workflows/move-to-main-repo.yaml
@@ -181,7 +181,8 @@ jobs:
- name: Prepare branch name
run: |
script_name="${{ steps.list_issues.outputs.script_name }}"
- branch_name="add-script-${script_name//[^a-zA-Z0-9_-]/}"
+ timestamp=$(date +%s)
+ branch_name="add-script-${script_name//[^a-zA-Z0-9_-]/}-${timestamp}"
echo "Using branch: $branch_name"
echo "branch_name=$branch_name" >> $GITHUB_ENV
@@ -194,6 +195,12 @@ jobs:
git clone https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/community-scripts/ProxmoxVE.git ProxmoxVE
cd ProxmoxVE
+ # Check if branch already exists remotely and delete it
+ if git ls-remote --exit-code --heads origin "$branch_name" >/dev/null 2>&1; then
+ echo "Branch $branch_name already exists remotely, deleting it..."
+ git push origin --delete "$branch_name" || true
+ fi
+
# Check if files already exist in target repo
case "$script_type" in
ct)
diff --git a/.github/workflows/scripts/app-test/pr-alpine-install.func b/.github/workflows/scripts/app-test/pr-alpine-install.func
index 9c13a6bc0..95d85cb72 100644
--- a/.github/workflows/scripts/app-test/pr-alpine-install.func
+++ b/.github/workflows/scripts/app-test/pr-alpine-install.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -83,4 +83,4 @@ motd_ssh() {
customize() {
return
-}
\ No newline at end of file
+}
diff --git a/.github/workflows/scripts/app-test/pr-build.func b/.github/workflows/scripts/app-test/pr-build.func
index 0e136ef04..2f143d3d8 100644
--- a/.github/workflows/scripts/app-test/pr-build.func
+++ b/.github/workflows/scripts/app-test/pr-build.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/.github/workflows/scripts/app-test/pr-create-lxc.sh b/.github/workflows/scripts/app-test/pr-create-lxc.sh
index 69b45a216..99d6b7742 100644
--- a/.github/workflows/scripts/app-test/pr-create-lxc.sh
+++ b/.github/workflows/scripts/app-test/pr-create-lxc.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/.github/workflows/scripts/app-test/pr-install.func b/.github/workflows/scripts/app-test/pr-install.func
index 2ff48df0c..8b45f154b 100644
--- a/.github/workflows/scripts/app-test/pr-install.func
+++ b/.github/workflows/scripts/app-test/pr-install.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Michel Roegl-Brunner (michelroegl-brunner)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -15,7 +15,7 @@ catch_errors() {
error_handler() {
local line_number="$1"
local command="$2"
- local error_message="Failure in line $line_number while executing command '$command'"
+ local error_message="Failure in line $line_number while executing command '$command'"
echo -e "\n$error_message\n" >&2
exit 1
}
@@ -90,4 +90,4 @@ motd_ssh() {
customize() {
return
-}
\ No newline at end of file
+}
diff --git a/.github/workflows/scripts/generate-app-headers.ps1 b/.github/workflows/scripts/generate-app-headers.ps1
new file mode 100644
index 000000000..022d9f029
--- /dev/null
+++ b/.github/workflows/scripts/generate-app-headers.ps1
@@ -0,0 +1,90 @@
+#!/usr/bin/env pwsh
+
+# Function for generating Figlet headers
+function Generate-Headers {
+ param (
+ [string]$BaseDir,
+ [string]$TargetSubdir,
+ [string]$SearchPattern
+ )
+
+ $HeadersDir = Join-Path $BaseDir $TargetSubdir
+
+ # Create headers directory if it doesn't exist
+ if (-not (Test-Path $HeadersDir)) {
+ New-Item -ItemType Directory -Path $HeadersDir -Force | Out-Null
+ }
+
+ # Remove existing header files
+ Get-ChildItem -Path $HeadersDir -File | Remove-Item -Force
+
+ # Determine search scope (recursive or not)
+ if ($SearchPattern -eq "**") {
+ $FileList = Get-ChildItem -Path $BaseDir -Filter "*.sh" -Recurse -File
+ }
+ else {
+ $FileList = Get-ChildItem -Path $BaseDir -Filter "*.sh" -File
+ }
+
+ foreach ($Script in $FileList) {
+ # Extract APP name from script
+ $Content = Get-Content $Script.FullName -Raw
+ if ($Content -match 'APP="([^"]+)"') {
+ $AppName = $Matches[1]
+
+ $OutputFile = Join-Path $HeadersDir $Script.BaseName
+
+ # Generate figlet output
+ try {
+ $FigletOutput = & figlet -w 500 -f slant $AppName 2>&1
+
+ if ($LASTEXITCODE -eq 0 -and $FigletOutput) {
+ $FigletOutput | Out-File -FilePath $OutputFile -Encoding utf8
+ Write-Host "Generated: $OutputFile" -ForegroundColor Green
+ }
+ else {
+ Write-Host "Figlet failed for $AppName in $($Script.Name)" -ForegroundColor Yellow
+ }
+ }
+ catch {
+ Write-Host "Error running figlet for $AppName : $_" -ForegroundColor Red
+ }
+ }
+ else {
+ Write-Host "No APP name found in $($Script.Name), skipping." -ForegroundColor Gray
+ }
+ }
+}
+
+# Check if figlet is available
+try {
+ $null = Get-Command figlet -ErrorAction Stop
+}
+catch {
+ Write-Host "Error: figlet is not installed or not in PATH" -ForegroundColor Red
+ Write-Host "`nInstallation options:" -ForegroundColor Yellow
+ Write-Host "1. Using Scoop (recommended):" -ForegroundColor Cyan
+ Write-Host " scoop install figlet" -ForegroundColor White
+ Write-Host "`n2. Manual download:" -ForegroundColor Cyan
+ Write-Host " Download from: https://github.com/cmatsuoka/figlet/releases" -ForegroundColor White
+ Write-Host " Extract and add to PATH" -ForegroundColor White
+ Write-Host "`n3. Using WSL:" -ForegroundColor Cyan
+ Write-Host " Run the bash version: bash generate-app-headers.sh" -ForegroundColor White
+ exit 1
+}
+
+# Change to script directory
+$ScriptDir = Split-Path -Parent $PSCommandPath
+$RepoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $ScriptDir))
+Set-Location $RepoRoot
+
+Write-Host "Processing ct/ directory..." -ForegroundColor Cyan
+Generate-Headers -BaseDir ".\ct" -TargetSubdir "headers" -SearchPattern "*"
+
+Write-Host "`nProcessing tools/ directory..." -ForegroundColor Cyan
+Generate-Headers -BaseDir ".\tools" -TargetSubdir "headers" -SearchPattern "**"
+
+Write-Host "`nProcessing vm/ directory..." -ForegroundColor Cyan
+Generate-Headers -BaseDir ".\vm" -TargetSubdir "headers" -SearchPattern "*"
+
+Write-Host "`nCompleted processing all sections." -ForegroundColor Green
diff --git a/.github/workflows/update_issue.yml b/.github/workflows/update_issue.yml
new file mode 100644
index 000000000..6f0cc64bb
--- /dev/null
+++ b/.github/workflows/update_issue.yml
@@ -0,0 +1,159 @@
+name: Update Issue on PR Merge
+
+on:
+ pull_request:
+ types: [closed]
+ branches:
+ - main
+
+permissions:
+ issues: write
+ pull-requests: read
+
+jobs:
+ update_issues:
+ if: github.event.pull_request.merged == true && github.repository == 'community-scripts/ProxmoxVED'
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Extract Script Names from Changed Files
+ id: extract_scripts
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
+
+ SCRIPT_NAMES=()
+
+ while IFS= read -r FILE; do
+ if [[ $FILE =~ ^ct/(.+)\.sh$ ]]; then
+ SCRIPT_NAME="${BASH_REMATCH[1]}"
+ if [[ ! " ${SCRIPT_NAMES[@]} " =~ " ${SCRIPT_NAME} " ]]; then
+ SCRIPT_NAMES+=("$SCRIPT_NAME")
+ fi
+ elif [[ $FILE =~ ^install/(.+)-install\.sh$ ]]; then
+ SCRIPT_NAME="${BASH_REMATCH[1]}"
+ if [[ ! " ${SCRIPT_NAMES[@]} " =~ " ${SCRIPT_NAME} " ]]; then
+ SCRIPT_NAMES+=("$SCRIPT_NAME")
+ fi
+ fi
+ done <<< "$CHANGED_FILES"
+
+ if [ ${#SCRIPT_NAMES[@]} -eq 0 ]; then
+ echo "No script files found in PR"
+ echo "script_names=[]" >> $GITHUB_OUTPUT
+ exit 0
+ fi
+
+ JSON_NAMES=$(printf '%s\n' "${SCRIPT_NAMES[@]}" | jq -R . | jq -s -c .)
+ echo "script_names=$JSON_NAMES" >> $GITHUB_OUTPUT
+ echo "Found script names: ${SCRIPT_NAMES[*]}"
+
+ - name: Process Each Script
+ if: steps.extract_scripts.outputs.script_names != '[]'
+ uses: actions/github-script@v7
+ env:
+ PR_AUTHOR: ${{ github.event.pull_request.user.login }}
+ SCRIPT_NAMES: ${{ steps.extract_scripts.outputs.script_names }}
+ with:
+ script: |
+ const scriptNames = JSON.parse(process.env.SCRIPT_NAMES);
+ const prAuthor = process.env.PR_AUTHOR;
+ const message = `@${prAuthor} This PR got merged now and is in the testing phase, it will be migrated to ProxmoxVE when testing is completed`;
+ const labelName = 'Ready For Testing';
+
+ for (const scriptName of scriptNames) {
+ console.log(`Processing script: ${scriptName}`);
+
+ const { data: issues } = await github.rest.issues.listForRepo({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ state: 'open',
+ per_page: 100
+ });
+
+ const scriptNameLower = scriptName.toLowerCase();
+ let existingIssue = issues.find(issue =>
+ !issue.pull_request && issue.title.toLowerCase() === scriptNameLower
+ );
+
+ if (!existingIssue) {
+ const { data: searchResults } = await github.rest.search.issuesAndPullRequests({
+ q: `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open ${scriptName}`,
+ per_page: 100
+ });
+
+ existingIssue = searchResults.items.find(issue =>
+ issue.title.toLowerCase() === scriptNameLower
+ );
+ }
+
+ if (existingIssue) {
+ console.log(`Found existing issue #${existingIssue.number}: ${existingIssue.title}`);
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: existingIssue.number,
+ body: message
+ });
+
+ const { data: labels } = await github.rest.issues.listLabelsOnIssue({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: existingIssue.number
+ });
+
+ const hasLabel = labels.some(label => label.name === labelName);
+
+ if (!hasLabel) {
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: existingIssue.number,
+ labels: [labelName]
+ });
+ console.log(`Added "${labelName}" label to issue #${existingIssue.number}`);
+ } else {
+ console.log(`Issue #${existingIssue.number} already has "${labelName}" label`);
+ }
+ } else {
+ console.log(`No existing issue found for "${scriptName}", creating new issue`);
+
+ const scriptType = 'CT (LXC Container)';
+
+ const formattedName = scriptName
+ .split(/[-_]/)
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
+ .join(' ');
+
+ const issueBody = '# π οΈ **New Script**\n' +
+ 'Create an Issue when you want to merge a new Script. The name of the Issue must be the same as your APP.sh file. (Example: SnipeIT, snipeit.sh; Alpine-Docker, alpine-docker.sh)\n\n' +
+ '### Name of the Script\n\n' +
+ formattedName + '\n\n' +
+ '### Script Type\n\n' +
+ scriptType + '\n\n' +
+ '### π Script Details\n\n' +
+ 'This script has been merged and is ready for testing. ';
+
+ const { data: newIssue } = await github.rest.issues.create({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ title: scriptName,
+ body: issueBody,
+ labels: [labelName]
+ });
+
+ console.log(`Created new issue #${newIssue.number}: ${newIssue.title}`);
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: newIssue.number,
+ body: message
+ });
+ }
+ }
+
diff --git a/.vscode/.shellcheckrc b/.vscode/.shellcheckrc
index 5cafdf6aa..4631bd3af 100644
--- a/.vscode/.shellcheckrc
+++ b/.vscode/.shellcheckrc
@@ -1 +1 @@
-disable=SC2034,SC1091,SC2155,SC2086,SC2317,SC2181
+disable=SC2034,SC1091,SC2155,SC2086,SC2317,SC2181,SC2164
diff --git a/bak/core_bak/build copy 2.func b/bak/core_bak/build copy 2.func
index b0b0404cd..45b304253 100644
--- a/bak/core_bak/build copy 2.func
+++ b/bak/core_bak/build copy 2.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
# Revision: 1
diff --git a/bak/core_bak/build refactor_menu.func b/bak/core_bak/build refactor_menu.func
index 93e3b7cfd..0c37261e2 100644
--- a/bak/core_bak/build refactor_menu.func
+++ b/bak/core_bak/build refactor_menu.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
# Revision: 1
diff --git a/bak/core_bak/build.func - advanced-backup-20251127-154005.func b/bak/core_bak/build.func - advanced-backup-20251127-154005.func
index 2e7920e6b..f7a8acd96 100644
--- a/bak/core_bak/build.func - advanced-backup-20251127-154005.func
+++ b/bak/core_bak/build.func - advanced-backup-20251127-154005.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/build.func.backup-20251029-123804 b/bak/deferred/build.func.backup-20251029-123804
index 9c8a1fc84..3bd10337c 100644
--- a/bak/deferred/build.func.backup-20251029-123804
+++ b/bak/deferred/build.func.backup-20251029-123804
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/build.func.backup-20251029-124205 b/bak/deferred/build.func.backup-20251029-124205
index 7e0556d61..919b0001a 100644
--- a/bak/deferred/build.func.backup-20251029-124205
+++ b/bak/deferred/build.func.backup-20251029-124205
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/build.func.backup-20251029-124307 b/bak/deferred/build.func.backup-20251029-124307
index d452f4637..2d514c644 100644
--- a/bak/deferred/build.func.backup-20251029-124307
+++ b/bak/deferred/build.func.backup-20251029-124307
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/build.func.backup-20251029-124334 b/bak/deferred/build.func.backup-20251029-124334
index d452f4637..2d514c644 100644
--- a/bak/deferred/build.func.backup-20251029-124334
+++ b/bak/deferred/build.func.backup-20251029-124334
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/build.func.backup-refactoring-20251029-125644 b/bak/deferred/build.func.backup-refactoring-20251029-125644
index d452f4637..2d514c644 100644
--- a/bak/deferred/build.func.backup-refactoring-20251029-125644
+++ b/bak/deferred/build.func.backup-refactoring-20251029-125644
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Revision: 1
diff --git a/bak/deferred/create_lxc.sh b/bak/deferred/create_lxc.sh
index a85f27478..31fb86c94 100644
--- a/bak/deferred/create_lxc.sh
+++ b/bak/deferred/create_lxc.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/ct/almalinux.sh b/ct/almalinux.sh
index 955caf418..58d9c00a6 100644
--- a/ct/almalinux.sh
+++ b/ct/almalinux.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://almalinux.org/
@@ -37,5 +37,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/alpine-loki.sh b/ct/alpine-loki.sh
new file mode 100644
index 000000000..49f04ca13
--- /dev/null
+++ b/ct/alpine-loki.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: hoholms
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/grafana/loki
+
+APP="Alpine-Loki"
+var_tags="${var_tags:-alpine;monitoring}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-256}"
+var_disk="${var_disk:-1}"
+var_os="${var_os:-alpine}"
+var_version="${var_version:-3.22}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ if ! apk -e info newt >/dev/null 2>&1; then
+ apk add -q newt
+ fi
+ LXCIP=$(ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
+ while true; do
+ CHOICE=$(
+ whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --menu "Select option" 11 58 3 \
+ "1" "Check for Loki Updates" \
+ "2" "Allow 0.0.0.0 for listening" \
+ "3" "Allow only ${LXCIP} for listening" 3>&2 2>&1 1>&3
+ )
+ exit_status=$?
+ if [ $exit_status == 1 ]; then
+ clear
+ exit-script
+ fi
+ header_info
+ case $CHOICE in
+ 1)
+ $STD apk -U upgrade
+ msg_ok "Updated successfully!"
+ exit
+ ;;
+ 2)
+ sed -i -e "s/cfg:server.http_addr=.*/cfg:server.http_addr=0.0.0.0/g" /etc/conf.d/loki
+ service loki restart
+ msg_ok "Allowed listening on all interfaces!"
+ exit
+ ;;
+ 3)
+ sed -i -e "s/cfg:server.http_addr=.*/cfg:server.http_addr=$LXCIP/g" /etc/conf.d/loki
+ service loki restart
+ msg_ok "Allowed listening only on ${LXCIP}!"
+ exit
+ ;;
+ esac
+ done
+ exit 0
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${APP} should be reachable by going to the following URL.
+ ${BL}http://${IP}:3100${CL} \n"
+echo -e "Promtail should be reachable by going to the following URL.
+ ${BL}http://${IP}:9080${CL} \n"
diff --git a/ct/alpine-ntfy.sh b/ct/alpine-ntfy.sh
index 4fc65b5d1..3a36648b0 100644
--- a/ct/alpine-ntfy.sh
+++ b/ct/alpine-ntfy.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: cobalt (cobaltgit)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://ntfy.sh/
@@ -27,14 +27,15 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating ntfy LXC"
$STD apk -U upgrade
setcap 'cap_net_bind_service=+ep' /usr/bin/ntfy
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated ntfy LXC"
msg_info "Restarting ntfy"
rc-service ntfy restart
msg_ok "Restarted ntfy"
+ msg_ok "Updated successfully!"
exit
}
@@ -42,7 +43,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/alpine-valkey.sh b/ct/alpine-valkey.sh
new file mode 100644
index 000000000..2765aff7f
--- /dev/null
+++ b/ct/alpine-valkey.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: pshankinclarke (lazarillo)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://valkey.io/
+
+APP="Alpine-Valkey"
+var_tags="${var_tags:-alpine;database}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-256}"
+var_disk="${var_disk:-1}"
+var_os="${var_os:-alpine}"
+var_version="${var_version:-3.22}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ if ! apk -e info newt >/dev/null 2>&1; then
+ apk add -q newt
+ fi
+ LXCIP=$(ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
+ while true; do
+ CHOICE=$(
+ whiptail --backtitle "Proxmox VE Helper Scripts" --title "Valkey Management" --menu "Select option" 11 58 3 \
+ "1" "Update Valkey" \
+ "2" "Allow 0.0.0.0 for listening" \
+ "3" "Allow only ${LXCIP} for listening" 3>&2 2>&1 1>&3
+ )
+ exit_status=$?
+ if [ $exit_status == 1 ]; then
+ clear
+ exit-script
+ fi
+ header_info
+ case $CHOICE in
+ 1)
+ msg_info "Updating Valkey"
+ apk update && apk upgrade valkey
+ rc-service valkey restart
+ msg_ok "Updated Valkey"
+ msg_ok "Updated successfully!"
+ exit
+ ;;
+ 2)
+ msg_info "Setting Valkey to listen on all interfaces"
+ sed -i 's/^bind .*/bind 0.0.0.0/' /etc/valkey/valkey.conf
+ rc-service valkey restart
+ msg_ok "Valkey now listens on all interfaces!"
+ exit
+ ;;
+ 3)
+ msg_info "Setting Valkey to listen only on ${LXCIP}"
+ sed -i "s/^bind .*/bind ${LXCIP}/" /etc/valkey/valkey.conf
+ rc-service valkey restart
+ msg_ok "Valkey now listens only on ${LXCIP}!"
+ exit
+ ;;
+ esac
+ done
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${APP} should be reachable on port 6379.
+ ${BL}valkey-cli -h ${IP} -p 6379${CL} \n"
diff --git a/ct/alpine.sh b/ct/alpine.sh
index 51767cb01..b843597ff 100644
--- a/ct/alpine.sh
+++ b/ct/alpine.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://alpinelinux.org/
@@ -38,4 +38,4 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/ct/ampache.sh b/ct/ampache.sh
new file mode 100644
index 000000000..ef6bb7903
--- /dev/null
+++ b/ct/ampache.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (Canbiz)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/ampache/ampache
+
+APP="Ampache"
+var_tags="${var_tags:-music}"
+var_disk="${var_disk:-5}"
+var_cpu="${var_cpu:-4}"
+var_ram="${var_ram:-2048}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -d /opt/ampache ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ if check_for_gh_release "Ampache" "ampache/ampache"; then
+ import_local_ip
+ msg_info "Stopping Apache"
+ systemctl stop apache2
+ msg_ok "Stopped Apache"
+
+ msg_info "Backing up Configuration"
+ cp /opt/ampache/config/ampache.cfg.php /tmp/ampache.cfg.php.backup
+ cp /opt/ampache/public/rest/.htaccess /tmp/ampache_rest.htaccess.backup
+ cp /opt/ampache/public/play/.htaccess /tmp/ampache_play.htaccess.backup
+ msg_ok "Backed up Configuration"
+
+ msg_info "Backup Ampache Folder"
+ rm -rf /opt/ampache_backup
+ mv /opt/ampache /opt/ampache_backup
+ msg_ok "Backed up Ampache"
+
+ fetch_and_deploy_gh_release "Ampache" "ampache/ampache" "release" "latest" "/opt/ampache" "ampache-*_all_php8.4.zip"
+
+ msg_info "Restoring Configuration"
+ cp /tmp/ampache.cfg.php.backup /opt/ampache/config/ampache.cfg.php
+ cp /tmp/ampache_rest.htaccess.backup /opt/ampache/public/rest/.htaccess
+ cp /tmp/ampache_play.htaccess.backup /opt/ampache/public/play/.htaccess
+ chmod 664 /opt/ampache/public/rest/.htaccess /opt/ampache/public/play/.htaccess
+ chown -R www-data:www-data /opt/ampache
+ msg_ok "Restored Configuration"
+
+ msg_info "Cleaning up"
+ rm -f /tmp/ampache*.backup
+ msg_ok "Cleaned up"
+
+ msg_info "Starting Apache"
+ systemctl start apache2
+ msg_ok "Started Apache"
+ msg_ok "Updated successfully!"
+ msg_custom "β οΈ" "${YW}" "Complete database update by visiting: http://${LOCAL_IP}/update.php"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/install.php${CL}"
diff --git a/ct/byparr.sh b/ct/byparr.sh
index 4ebeb3a68..62104bb11 100644
--- a/ct/byparr.sh
+++ b/ct/byparr.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: luismco
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/ThePhaseless/Byparr
@@ -33,12 +33,12 @@ function update_script() {
systemctl stop byparr
msg_ok "Stopped Service"
- fetch_and_deploy_gh_release "Byparr" "ThePhaseless/Byparr"
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Byparr" "ThePhaseless/Byparr"
msg_info "Starting Service"
systemctl start byparr
msg_ok "Started Service"
- msg_ok "Updated Successfully!"
+ msg_ok "Updated successfully!"
fi
exit
}
@@ -47,7 +47,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8191${CL}"
diff --git a/ct/centos.sh b/ct/centos.sh
index a6ee3de84..54dea3950 100644
--- a/ct/centos.sh
+++ b/ct/centos.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.centos.org/centos-stream/
@@ -27,9 +27,9 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating CentOS LXC"
$STD dnf -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated CentOS LXC"
exit
}
@@ -37,5 +37,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/cronmaster.sh b/ct/cronmaster.sh
new file mode 100644
index 000000000..7a2e0ac50
--- /dev/null
+++ b/ct/cronmaster.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source:
+
+APP="CRONMASTER"
+var_tags="${var_tags:-}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-8}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+#var_fuse="${var_fuse:-no}"
+#var_tun="${var_tun:-no}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/cronmaster ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ msg_info "Updating Debian LXC"
+ $STD apt update
+ $STD apt upgrade -y
+ msg_ok "Updated Debian LXC"
+ cleanup_lxc
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!"
+msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/databasus.sh b/ct/databasus.sh
new file mode 100644
index 000000000..c0eab526b
--- /dev/null
+++ b/ct/databasus.sh
@@ -0,0 +1,80 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/databasus/databasus
+
+APP="Databasus"
+var_tags="${var_tags:-backup;postgresql;database}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-8}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -f /opt/databasus/databasus ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "databasus" "databasus/databasus"; then
+ msg_info "Stopping Databasus"
+ $STD systemctl stop databasus
+ msg_ok "Stopped Databasus"
+
+ msg_info "Backing up Configuration"
+ cp /opt/databasus/.env /tmp/databasus.env.bak
+ msg_ok "Backed up Configuration"
+
+ msg_info "Updating Databasus"
+ fetch_and_deploy_gh_release "databasus" "databasus/databasus" "tarball" "latest" "/opt/databasus"
+
+ cd /opt/databasus/frontend
+ $STD npm ci
+ $STD npm run build
+
+ cd /opt/databasus/backend
+ $STD go mod download
+ $STD /root/go/bin/swag init -g cmd/main.go -o swagger
+ $STD env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o databasus ./cmd/main.go
+ mv /opt/databasus/backend/databasus /opt/databasus/databasus
+
+ cp -r /opt/databasus/frontend/dist/* /opt/databasus/ui/build/
+ cp -r /opt/databasus/backend/migrations /opt/databasus/
+ chown -R postgres:postgres /opt/databasus
+ msg_ok "Updated Databasus"
+
+ msg_info "Restoring Configuration"
+ cp /tmp/databasus.env.bak /opt/databasus/.env
+ rm -f /tmp/databasus.env.bak
+ chown postgres:postgres /opt/databasus/.env
+ msg_ok "Restored Configuration"
+
+ msg_info "Starting Databasus"
+ $STD systemctl start databasus
+ msg_ok "Started Databasus"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/debian.sh b/ct/debian.sh
index e5bdd8a3c..88fbb5550 100644
--- a/ct/debian.sh
+++ b/ct/debian.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source:
@@ -30,10 +30,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Debian LXC"
$STD apt update
$STD apt upgrade -y
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Debian LXC"
cleanup_lxc
exit
}
@@ -42,5 +42,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/deferred/alpine-homarr.sh b/ct/deferred/alpine-homarr.sh
index c78398d65..785d0ebaa 100644
--- a/ct/deferred/alpine-homarr.sh
+++ b/ct/deferred/alpine-homarr.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | Co-Author: MickLesk (Canbiz) | Co-Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://homarr.dev/
@@ -108,7 +108,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7575${CL}"
diff --git a/ct/deferred/ampache.sh b/ct/deferred/ampache.sh
deleted file mode 100644
index ada18f098..000000000
--- a/ct/deferred/ampache.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: MickLesk (Canbiz)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source:
-
-APP="Ampache"
-var_tags="${var_tags:-music}"
-var_disk="${var_disk:-5}"
-var_cpu="${var_cpu:-4}"
-var_ram="${var_ram:-2048}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/ampache ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
- msg_info "Updating ${APP} LXC"
- cd /opt/ampache
- ###### Update Script Here ######
- msg_ok "Updated Successfully"
- else
- msg_ok "No update required. ${APP} is already at v${RELEASE}"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/install.php${CL}"
diff --git a/ct/deferred/docspell.sh b/ct/deferred/docspell.sh
index 93eb6806f..9c3764982 100644
--- a/ct/deferred/docspell.sh
+++ b/ct/deferred/docspell.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/community-scripts/ProxmoxVE
@@ -45,7 +45,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7880${CL}"
diff --git a/ct/deferred/jumpserver.sh b/ct/deferred/jumpserver.sh
index f512024c9..4ac5edf38 100644
--- a/ct/deferred/jumpserver.sh
+++ b/ct/deferred/jumpserver.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: NΓcolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/jumpserver/jumpserver
@@ -59,7 +59,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/deferred/kanba.sh b/ct/deferred/kanba.sh
index 270f5e00f..848b6a798 100644
--- a/ct/deferred/kanba.sh
+++ b/ct/deferred/kanba.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/Kanba-co/kanba
@@ -38,7 +38,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/deferred/manyfold.sh b/ct/deferred/manyfold.sh
deleted file mode 100644
index 2d782d551..000000000
--- a/ct/deferred/manyfold.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: bvdberg01
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/manyfold3d/manyfold
-
-APP="Manyfold"
-var_tags="${var_tags:-network}"
-var_cpu="${var_cpu:-4}"
-var_ram="${var_ram:-4096}"
-var_disk="${var_disk:-15}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/manyfold ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- RELEASE=$(curl -fsSL https://api.github.com/repos/benjaminjonard/manyfold/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 Service"
- systemctl stop apache2
- msg_ok "Stopped Service"
-
- msg_info "Updating ${APP} to v${RELEASE}"
- cd /opt
- mv /opt/manyfold/ /opt/manyfold-backup
-
- echo "${RELEASE}" >/opt/${APP}_version.txt
- msg_ok "Updated $APP to v${RELEASE}"
-
- msg_info "Starting Service"
- systemctl start service
- msg_ok "Started Service"
-
- msg_info "Cleaning up"
- rm -r "/opt/${RELEASE}.zip"
- rm -r /opt/manyfold-backup
- msg_ok "Cleaned"
- msg_ok "Updated Successfully"
- else
- msg_ok "No update required. ${APP} is already at v${RELEASE}"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/deferred/maxun.sh b/ct/deferred/maxun.sh
index ab303b763..4d39ecc5e 100644
--- a/ct/deferred/maxun.sh
+++ b/ct/deferred/maxun.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/getmaxun/maxun
@@ -43,7 +43,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/petio.sh b/ct/deferred/maybe_death/petio.sh
similarity index 80%
rename from ct/petio.sh
rename to ct/deferred/maybe_death/petio.sh
index f9c4d1370..9771b125f 100644
--- a/ct/petio.sh
+++ b/ct/deferred/maybe_death/petio.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://petio.tv/
@@ -26,12 +26,13 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP"
- systemctl stop petio.service
+ msg_info "Updating Pepito"
+ systemctl stop petio
curl -fsSL https://petio.tv/releases/latest -o petio-latest.zip
$STD unzip petio-latest.zip -d /opt/Petio
- systemctl start petio.service
- msg_ok "Updated $APP"
+ systemctl start petio
+ msg_ok "Updated Pepito"
+ msg_ok "Updated successfully!"
exit
}
@@ -39,7 +40,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7777${CL}"
diff --git a/ct/deferred/netbootxyz.sh b/ct/deferred/netbootxyz.sh
index 201073af9..2205aec37 100644
--- a/ct/deferred/netbootxyz.sh
+++ b/ct/deferred/netbootxyz.sh
@@ -124,6 +124,6 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${APP} should be reachable by going to the following URL.
${BL}http://${IP}:3000${CL} \n"
diff --git a/ct/deferred/nginxproxymanager.sh b/ct/deferred/nginxproxymanager.sh
index b1ff024d7..6d59efe8f 100644
--- a/ct/deferred/nginxproxymanager.sh
+++ b/ct/deferred/nginxproxymanager.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nginxproxymanager.com/
@@ -154,7 +154,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:81${CL}"
diff --git a/ct/deferred/ocis.sh b/ct/deferred/ocis.sh
index 167b4593d..b48547579 100644
--- a/ct/deferred/ocis.sh
+++ b/ct/deferred/ocis.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.debian.org/
@@ -38,7 +38,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9200${CL}"
diff --git a/ct/deferred/pixelfed.sh b/ct/deferred/pixelfed.sh
deleted file mode 100644
index 8ddab519c..000000000
--- a/ct/deferred/pixelfed.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: MickLesk (Canbiz)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source:
-
-APP="Pixelfed"
-var_tags="${var_tags:-pictures}"
-var_disk="${var_disk:-7}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
-
-header_info "$APP"
-variables
-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 -fsSL 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
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${APP} Setup should be reachable by going to the following URL.
- ${BL}http://${IP}:8000${CL} \n"
diff --git a/ct/deferred/polaris.sh b/ct/deferred/polaris.sh
index c290d7706..ab9edabd5 100644
--- a/ct/deferred/polaris.sh
+++ b/ct/deferred/polaris.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/agersant/polaris
@@ -34,7 +34,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5050${CL}"
diff --git a/ct/deferred/roundcubemail.sh b/ct/deferred/roundcubemail.sh
index 75d0e3bcd..93ae76e8e 100644
--- a/ct/deferred/roundcubemail.sh
+++ b/ct/deferred/roundcubemail.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source:
@@ -59,6 +59,6 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${APP} should be reachable by going to the following URL.
${BL}http://${IP}/installer ${CL} \n"
diff --git a/ct/rybbit.sh b/ct/deferred/rybbit.sh
similarity index 83%
rename from ct/rybbit.sh
rename to ct/deferred/rybbit.sh
index 62447664c..621e0e1b3 100644
--- a/ct/rybbit.sh
+++ b/ct/deferred/rybbit.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/rybbit-io/rybbit
@@ -27,10 +27,11 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Rybbit LXC"
$STD apt-get update
$STD apt-get -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Rybbit LXC"
+ msg_ok "Updated successfully!"
exit
}
@@ -38,5 +39,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!\n"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/deferred/squirrelserversmanager.sh b/ct/deferred/squirrelserversmanager.sh
index 4403ab5f0..94e85d30e 100644
--- a/ct/deferred/squirrelserversmanager.sh
+++ b/ct/deferred/squirrelserversmanager.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source:
@@ -52,6 +52,6 @@ msg_info "Setting Container to Normal Resources"
pct set $CTID -memory 1024
pct set $CTID -cores 1
msg_ok "Set Container to Normal Resources"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${APP} should be reachable by going to the following URL.
${BL}http://${IP}:80${CL} \n"
diff --git a/ct/transmission-openvpn.sh b/ct/deferred/transmission-openvpn.sh
similarity index 94%
rename from ct/transmission-openvpn.sh
rename to ct/deferred/transmission-openvpn.sh
index 647339241..313ab7db9 100644
--- a/ct/transmission-openvpn.sh
+++ b/ct/deferred/transmission-openvpn.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: SunFlowerOwl
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/haugene/docker-transmission-openvpn
@@ -67,12 +67,9 @@ function update_script() {
fi
msg_info "Cleaning up"
- $STD apt -y autoremove
- $STD apt -y autoclean
- $STD apt -y clean
rm -rf /opt/docker-transmission-openvpn
msg_ok "Cleaned"
-
+ msg_ok "Updated successfully!"
exit
}
@@ -80,7 +77,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9091${CL}"
diff --git a/ct/devuan.sh b/ct/devuan.sh
index 82bd83f83..489c1f8d1 100644
--- a/ct/devuan.sh
+++ b/ct/devuan.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.devuan.org/
@@ -27,10 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Devuan LXC"
$STD apt-get update
$STD apt-get -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Devuan LXC"
exit
}
@@ -38,5 +38,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/ente.sh b/ct/ente.sh
index 5733886ca..c234048b7 100644
--- a/ct/ente.sh
+++ b/ct/ente.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.debian.org/
@@ -8,10 +8,10 @@ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxV
APP="Ente"
var_tags="${var_tags:-photos}"
var_cpu="${var_cpu:-4}"
-var_ram="${var_ram:-4096}"
-var_disk="${var_disk:-10}"
+var_ram="${var_ram:-6144}"
+var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
+var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -20,23 +20,25 @@ color
catch_errors
function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /var ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- msg_info "Updating $APP LXC"
- $STD apt-get update
- $STD apt-get -y upgrade
- msg_ok "Updated $APP LXC"
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /var ]]; then
+ msg_error "No ${APP} Installation Found!"
exit
+ fi
+ msg_info "Updating Ente LXC"
+ $STD apt-get update
+ $STD apt-get -y upgrade
+ msg_ok "Updated Ente LXC"
+ exit
}
start
build_container
description
-msg_ok "Completed Successfully!"
-msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/fedora.sh b/ct/fedora.sh
index df252051e..66a67247c 100644
--- a/ct/fedora.sh
+++ b/ct/fedora.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://fedoraproject.org/
@@ -27,9 +27,9 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Fedora LXC"
$STD dnf -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Fedora LXC"
exit
}
@@ -37,5 +37,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/forgejo-runner.sh b/ct/forgejo-runner.sh
new file mode 100644
index 000000000..1dfe36ebc
--- /dev/null
+++ b/ct/forgejo-runner.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Simon Friedrich
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://forgejo.org/
+
+APP="Forgejo Runner"
+var_tags="${var_tags:-ci}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-8}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-12}"
+
+var_unprivileged="${var_unprivileged:-1}"
+var_nesting="${var_nesting:-1}"
+var_keyctl="${var_keyctl:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -f /usr/local/bin/forgejo-runner ]]; then
+ msg_error "No ${APP} installation found!"
+ exit 1
+ fi
+
+ msg_info "Stopping Services"
+ systemctl stop forgejo-runner
+ msg_ok "Stopped Services"
+
+ RELEASE=$(curl -fsSL https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | grep -oP '"tag_name":\s*"\K[^"]+' | sed 's/^v//')
+ msg_info "Updating Forgejo Runner to v${RELEASE}"
+ curl -fsSL "https://code.forgejo.org/forgejo/runner/releases/download/v${RELEASE}/forgejo-runner-linux-amd64" -o forgejo-runner
+ chmod +x /usr/local/bin/forgejo-runner
+ msg_ok "Updated Forgejo Runner"
+
+ msg_info "Starting Services"
+ systemctl start forgejo-runner
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
diff --git a/ct/freepbx.sh b/ct/freepbx.sh
index fd2395c91..e16a1c47a 100644
--- a/ct/freepbx.sh
+++ b/ct/freepbx.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/refs/heads/freepbx/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Arian Nasr (arian-nasr)
# Updated by: Javier Pastor (vsc55)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -30,16 +30,16 @@ function update_script() {
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating FreePBX LXC"
$STD apt-get update
$STD apt-get -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated FreePBX LXC"
- msg_info "Updating $APP Modules"
+ msg_info "Updating FreePBX Modules"
$STD fwconsole ma updateall
$STD fwconsole reload
- msg_ok "Updated $APP Modules"
-
+ msg_ok "Updated FreePBX Modules"
+ msg_ok "Updated successfully!"
exit
}
@@ -61,7 +61,7 @@ fi
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/frigate.sh b/ct/frigate.sh
index 9dd49dc19..ecdc17126 100644
--- a/ct/frigate.sh
+++ b/ct/frigate.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ) | Co-Author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/
@@ -35,7 +35,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}"
diff --git a/ct/garmin-grafana.sh b/ct/garmin-grafana.sh
index f0742dd82..cdda1b605 100644
--- a/ct/garmin-grafana.sh
+++ b/ct/garmin-grafana.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/raw/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: aliaksei135
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/arpanghosh8453/garmin-grafana
@@ -32,11 +32,11 @@ function update_script() {
RELEASE=$(curl -fsSL https://api.github.com/repos/arpanghosh8453/garmin-grafana/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
if [[ ! -d /opt/garmin-grafana/ ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
- msg_info "Stopping $APP"
+ msg_info "Stopping Services"
systemctl stop garmin-grafana
systemctl stop grafana-server
systemctl stop influxdb
- msg_ok "Stopped $APP"
+ msg_ok "Stopped Services"
if [[ ! -f /opt/garmin-grafana/.env ]]; then
msg_error "No .env file found in /opt/garmin-grafana/.env"
@@ -59,7 +59,6 @@ function update_script() {
mv "garmin-grafana-${RELEASE}/" "/opt/garmin-grafana"
rm -f "${RELEASE}.zip"
$STD uv sync --locked --project /opt/garmin-grafana/
- # shellcheck disable=SC2016
sed -i 's/\${DS_GARMIN_STATS}/garmin_influxdb/g' /opt/garmin-grafana/Grafana_Dashboard/Garmin-Grafana-Dashboard.json
sed -i 's/influxdb:8086/localhost:8086/' /opt/garmin-grafana/Grafana_Datasource/influxdb.yaml
sed -i "s/influxdb_user/${INFLUXDB_USER}/" /opt/garmin-grafana/Grafana_Datasource/influxdb.yaml
@@ -73,18 +72,17 @@ function update_script() {
cp -r /opt/garmin-grafana-backup/.garminconnect /opt/garmin-grafana/.garminconnect
msg_ok "Updated $APP to v${RELEASE}"
- msg_info "Starting $APP"
+ msg_info "Starting Services"
systemctl start garmin-grafana
systemctl start grafana-server
systemctl start influxdb
- msg_ok "Started $APP"
-
+ msg_ok "Started Services"
msg_info "Cleaning Up"
rm -rf /opt/garmin-grafana-backup
msg_ok "Cleanup Completed"
echo "${RELEASE}" >/opt/${APP}_version.txt
- msg_ok "Update Successful"
+ msg_ok "Updated Successfully!"
else
msg_ok "No update required. ${APP} is already at v${RELEASE}"
fi
@@ -95,7 +93,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/gentoo.sh b/ct/gentoo.sh
index fcb006b19..d26706d5d 100644
--- a/ct/gentoo.sh
+++ b/ct/gentoo.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.gentoo.org/
@@ -27,10 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Gentoo LXC"
$STD emerge --sync
$STD emerge --quiet --update --deep @world
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Gentoo LXC"
exit
}
@@ -38,5 +38,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/headers/almalinux b/ct/headers/almalinux
new file mode 100644
index 000000000..1ff1dc19b
--- /dev/null
+++ b/ct/headers/almalinux
@@ -0,0 +1,6 @@
+ο»Ώ ___ __ __ _
+ / | / /___ ___ ____ _/ / (_)___ __ ___ __
+ / /| | / / __ `__ \/ __ `/ / / / __ \/ / / / |/_/
+ / ___ |/ / / / / / / /_/ / /___/ / / / / /_/ /> <
+/_/ |_/_/_/ /_/ /_/\__,_/_____/_/_/ /_/\__,_/_/|_|
+
diff --git a/ct/headers/alpine b/ct/headers/alpine
index ecf1e0554..2015c7841 100644
--- a/ct/headers/alpine
+++ b/ct/headers/alpine
@@ -1,4 +1,4 @@
- ___ __ _
+ο»Ώ ___ __ _
/ | / /___ (_)___ ___
/ /| | / / __ \/ / __ \/ _ \
/ ___ |/ / /_/ / / / / / __/
diff --git a/ct/headers/alpine-loki b/ct/headers/alpine-loki
new file mode 100644
index 000000000..7e829b1da
--- /dev/null
+++ b/ct/headers/alpine-loki
@@ -0,0 +1,6 @@
+ο»Ώ ___ __ _ __ __ _
+ / | / /___ (_)___ ___ / / ____ / /__(_)
+ / /| | / / __ \/ / __ \/ _ \______/ / / __ \/ //_/ /
+ / ___ |/ / /_/ / / / / / __/_____/ /___/ /_/ / ,< / /
+/_/ |_/_/ .___/_/_/ /_/\___/ /_____/\____/_/|_/_/
+ /_/
diff --git a/ct/headers/alpine-ntfy b/ct/headers/alpine-ntfy
index bc4164342..b97496fc9 100644
--- a/ct/headers/alpine-ntfy
+++ b/ct/headers/alpine-ntfy
@@ -1,4 +1,4 @@
- ___ __ _ __ ____
+ο»Ώ ___ __ _ __ ____
/ | / /___ (_)___ ___ ____ / /_/ __/_ __
/ /| | / / __ \/ / __ \/ _ \______/ __ \/ __/ /_/ / / /
/ ___ |/ / /_/ / / / / / __/_____/ / / / /_/ __/ /_/ /
diff --git a/ct/headers/alpine-valkey b/ct/headers/alpine-valkey
new file mode 100644
index 000000000..33e930808
--- /dev/null
+++ b/ct/headers/alpine-valkey
@@ -0,0 +1,6 @@
+ο»Ώ ___ __ _ _ __ ____
+ / | / /___ (_)___ ___ | | / /___ _/ / /_____ __ __
+ / /| | / / __ \/ / __ \/ _ \_____| | / / __ `/ / //_/ _ \/ / / /
+ / ___ |/ / /_/ / / / / / __/_____/ |/ / /_/ / / ,< / __/ /_/ /
+/_/ |_/_/ .___/_/_/ /_/\___/ |___/\__,_/_/_/|_|\___/\__, /
+ /_/ /____/
diff --git a/ct/headers/ampache b/ct/headers/ampache
new file mode 100644
index 000000000..68d2c033d
--- /dev/null
+++ b/ct/headers/ampache
@@ -0,0 +1,6 @@
+ο»Ώ ___ __
+ / | ____ ___ ____ ____ ______/ /_ ___
+ / /| | / __ `__ \/ __ \/ __ `/ ___/ __ \/ _ \
+ / ___ |/ / / / / / /_/ / /_/ / /__/ / / / __/
+/_/ |_/_/ /_/ /_/ .___/\__,_/\___/_/ /_/\___/
+ /_/
diff --git a/ct/headers/byparr b/ct/headers/byparr
new file mode 100644
index 000000000..0a6f89eca
--- /dev/null
+++ b/ct/headers/byparr
@@ -0,0 +1,6 @@
+ο»Ώ ____
+ / __ )__ ______ ____ ___________
+ / __ / / / / __ \/ __ `/ ___/ ___/
+ / /_/ / /_/ / /_/ / /_/ / / / /
+/_____/\__, / .___/\__,_/_/ /_/
+ /____/_/
diff --git a/ct/headers/centos b/ct/headers/centos
new file mode 100644
index 000000000..9a449f2b8
--- /dev/null
+++ b/ct/headers/centos
@@ -0,0 +1,6 @@
+ο»Ώ ______ __ ____ _____ _____ __
+ / ____/__ ____ / /_/ __ \/ ___/ / ___// /_________ ____ _____ ___
+ / / / _ \/ __ \/ __/ / / /\__ \ \__ \/ __/ ___/ _ \/ __ `/ __ `__ \
+/ /___/ __/ / / / /_/ /_/ /___/ / ___/ / /_/ / / __/ /_/ / / / / / /
+\____/\___/_/ /_/\__/\____//____/ /____/\__/_/ \___/\__,_/_/ /_/ /_/
+
diff --git a/ct/headers/cronmaster b/ct/headers/cronmaster
new file mode 100644
index 000000000..e4de81e88
--- /dev/null
+++ b/ct/headers/cronmaster
@@ -0,0 +1,6 @@
+ο»Ώ __________ ____ _ ____ ______ _____________________
+ / ____/ __ \/ __ \/ | / / |/ / | / ___/_ __/ ____/ __ \
+ / / / /_/ / / / / |/ / /|_/ / /| | \__ \ / / / __/ / /_/ /
+/ /___/ _, _/ /_/ / /| / / / / ___ |___/ // / / /___/ _, _/
+\____/_/ |_|\____/_/ |_/_/ /_/_/ |_/____//_/ /_____/_/ |_|
+
diff --git a/ct/headers/debian b/ct/headers/debian
index a6f474d46..54a409119 100644
--- a/ct/headers/debian
+++ b/ct/headers/debian
@@ -1,4 +1,4 @@
- ____ __ _
+ο»Ώ ____ __ _
/ __ \___ / /_ (_)___ _____
/ / / / _ \/ __ \/ / __ `/ __ \
/ /_/ / __/ /_/ / / /_/ / / / /
diff --git a/ct/headers/devuan b/ct/headers/devuan
new file mode 100644
index 000000000..a5ef3358d
--- /dev/null
+++ b/ct/headers/devuan
@@ -0,0 +1,6 @@
+ο»Ώ ____
+ / __ \___ _ ____ ______ _____
+ / / / / _ \ | / / / / / __ `/ __ \
+ / /_/ / __/ |/ / /_/ / /_/ / / / /
+/_____/\___/|___/\__,_/\__,_/_/ /_/
+
diff --git a/ct/headers/docker b/ct/headers/docker
deleted file mode 100644
index 907ffbaef..000000000
--- a/ct/headers/docker
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ __
- / __ \____ _____/ /_____ _____
- / / / / __ \/ ___/ //_/ _ \/ ___/
- / /_/ / /_/ / /__/ ,< / __/ /
-/_____/\____/\___/_/|_|\___/_/
-
diff --git a/ct/headers/ente b/ct/headers/ente
index f700a1f53..271fd8d3b 100644
--- a/ct/headers/ente
+++ b/ct/headers/ente
@@ -1,4 +1,4 @@
- ______ __
+ο»Ώ ______ __
/ ____/___ / /____
/ __/ / __ \/ __/ _ \
/ /___/ / / / /_/ __/
diff --git a/ct/headers/fedora b/ct/headers/fedora
new file mode 100644
index 000000000..81e950ee8
--- /dev/null
+++ b/ct/headers/fedora
@@ -0,0 +1,6 @@
+ο»Ώ ______ __
+ / ____/__ ____/ /___ _________ _
+ / /_ / _ \/ __ / __ \/ ___/ __ `/
+ / __/ / __/ /_/ / /_/ / / / /_/ /
+/_/ \___/\__,_/\____/_/ \__,_/
+
diff --git a/ct/headers/forgejo-runner b/ct/headers/forgejo-runner
new file mode 100644
index 000000000..5e3321610
--- /dev/null
+++ b/ct/headers/forgejo-runner
@@ -0,0 +1,6 @@
+ο»Ώ ______ _ ____
+ / ____/___ _________ ____ (_)___ / __ \__ ______ ____ ___ _____
+ / /_ / __ \/ ___/ __ `/ _ \ / / __ \ / /_/ / / / / __ \/ __ \/ _ \/ ___/
+ / __/ / /_/ / / / /_/ / __/ / / /_/ / / _, _/ /_/ / / / / / / / __/ /
+/_/ \____/_/ \__, /\___/_/ /\____/ /_/ |_|\__,_/_/ /_/_/ /_/\___/_/
+ /____/ /___/
diff --git a/ct/headers/freepbx b/ct/headers/freepbx
index 25541c2ed..15dc15e4a 100644
--- a/ct/headers/freepbx
+++ b/ct/headers/freepbx
@@ -1,4 +1,4 @@
- ______ ____ ____ _ __
+ο»Ώ ______ ____ ____ _ __
/ ____/_______ ___ / __ \/ __ ) |/ /
/ /_ / ___/ _ \/ _ \/ /_/ / __ | /
/ __/ / / / __/ __/ ____/ /_/ / |
diff --git a/ct/headers/frigate b/ct/headers/frigate
index 94ffd3a7d..cc1c3c84f 100644
--- a/ct/headers/frigate
+++ b/ct/headers/frigate
@@ -1,4 +1,4 @@
- ______ _ __
+ο»Ώ ______ _ __
/ ____/____(_)___ _____ _/ /____
/ /_ / ___/ / __ `/ __ `/ __/ _ \
/ __/ / / / / /_/ / /_/ / /_/ __/
diff --git a/ct/headers/garmin-grafana b/ct/headers/garmin-grafana
index 5509b8143..270b91452 100644
--- a/ct/headers/garmin-grafana
+++ b/ct/headers/garmin-grafana
@@ -1,4 +1,4 @@
- _ ____
+ο»Ώ _ ____
____ _____ __________ ___ (_)___ ____ __________ _/ __/___ _____ ____ _
/ __ `/ __ `/ ___/ __ `__ \/ / __ \______/ __ `/ ___/ __ `/ /_/ __ `/ __ \/ __ `/
/ /_/ / /_/ / / / / / / / / / / / /_____/ /_/ / / / /_/ / __/ /_/ / / / / /_/ /
diff --git a/ct/headers/gentoo b/ct/headers/gentoo
new file mode 100644
index 000000000..958bee88e
--- /dev/null
+++ b/ct/headers/gentoo
@@ -0,0 +1,6 @@
+ο»Ώ ______ __
+ / ____/__ ____ / /_____ ____
+ / / __/ _ \/ __ \/ __/ __ \/ __ \
+/ /_/ / __/ / / / /_/ /_/ / /_/ /
+\____/\___/_/ /_/\__/\____/\____/
+
diff --git a/ct/headers/gitea-mirror b/ct/headers/gitea-mirror
deleted file mode 100644
index 57003b058..000000000
--- a/ct/headers/gitea-mirror
+++ /dev/null
@@ -1,6 +0,0 @@
- _ __ _
- ____ _(_) /____ ____ _ ____ ___ (_)_____________ _____
- / __ `/ / __/ _ \/ __ `/_____/ __ `__ \/ / ___/ ___/ __ \/ ___/
- / /_/ / / /_/ __/ /_/ /_____/ / / / / / / / / / / /_/ / /
- \__, /_/\__/\___/\__,_/ /_/ /_/ /_/_/_/ /_/ \____/_/
-/____/
diff --git a/ct/headers/gwn-manager b/ct/headers/gwn-manager
new file mode 100644
index 000000000..6aacb372e
--- /dev/null
+++ b/ct/headers/gwn-manager
@@ -0,0 +1,6 @@
+ο»Ώ _______ ___ __ __ ___
+ / ____/ | / / | / / / |/ /___ _____ ____ _____ ____ _____
+ / / __ | | /| / / |/ /_____/ /|_/ / __ `/ __ \/ __ `/ __ `/ _ \/ ___/
+/ /_/ / | |/ |/ / /| /_____/ / / / /_/ / / / / /_/ / /_/ / __/ /
+\____/ |__/|__/_/ |_/ /_/ /_/\__,_/_/ /_/\__,_/\__, /\___/_/
+ /____/
diff --git a/ct/headers/heimdall-dashboard b/ct/headers/heimdall-dashboard
new file mode 100644
index 000000000..ced6c869b
--- /dev/null
+++ b/ct/headers/heimdall-dashboard
@@ -0,0 +1,6 @@
+ο»Ώ __ __ _ __ ____ ____ __ __ __
+ / / / /__ (_)___ ___ ____/ /___ _/ / / / __ \____ ______/ /_ / /_ ____ ____ __________/ /
+ / /_/ / _ \/ / __ `__ \/ __ / __ `/ / /_____/ / / / __ `/ ___/ __ \/ __ \/ __ \/ __ `/ ___/ __ /
+ / __ / __/ / / / / / / /_/ / /_/ / / /_____/ /_/ / /_/ (__ ) / / / /_/ / /_/ / /_/ / / / /_/ /
+/_/ /_/\___/_/_/ /_/ /_/\__,_/\__,_/_/_/ /_____/\__,_/____/_/ /_/_.___/\____/\__,_/_/ \__,_/
+
diff --git a/ct/headers/hoodik b/ct/headers/hoodik
new file mode 100644
index 000000000..2d9b951a1
--- /dev/null
+++ b/ct/headers/hoodik
@@ -0,0 +1,6 @@
+ο»Ώ __ __ ___ __
+ / / / /___ ____ ____/ (_) /__
+ / /_/ / __ \/ __ \/ __ / / //_/
+ / __ / /_/ / /_/ / /_/ / / ,<
+/_/ /_/\____/\____/\__,_/_/_/|_|
+
diff --git a/ct/headers/joplin-server b/ct/headers/joplin-server
deleted file mode 100644
index 68b32c8fa..000000000
--- a/ct/headers/joplin-server
+++ /dev/null
@@ -1,6 +0,0 @@
- __ ___ _____
- / /___ ____ / (_)___ / ___/___ ______ _____ _____
- __ / / __ \/ __ \/ / / __ \______\__ \/ _ \/ ___/ | / / _ \/ ___/
-/ /_/ / /_/ / /_/ / / / / / /_____/__/ / __/ / | |/ / __/ /
-\____/\____/ .___/_/_/_/ /_/ /____/\___/_/ |___/\___/_/
- /_/
diff --git a/ct/headers/kitchenowl b/ct/headers/kitchenowl
new file mode 100644
index 000000000..6f20ad457
--- /dev/null
+++ b/ct/headers/kitchenowl
@@ -0,0 +1,6 @@
+ο»Ώ __ __ _ __ __ ____ __
+ / //_/(_) /______/ /_ ___ ____ / __ \_ __/ /
+ / ,< / / __/ ___/ __ \/ _ \/ __ \/ / / / | /| / / /
+ / /| |/ / /_/ /__/ / / / __/ / / / /_/ /| |/ |/ / /
+/_/ |_/_/\__/\___/_/ /_/\___/_/ /_/\____/ |__/|__/_/
+
diff --git a/ct/headers/linkwarden b/ct/headers/linkwarden
new file mode 100644
index 000000000..d4e605619
--- /dev/null
+++ b/ct/headers/linkwarden
@@ -0,0 +1,6 @@
+ο»Ώ __ _ __ __
+ / / (_)___ / /___ ______ __________/ /__ ____
+ / / / / __ \/ //_/ | /| / / __ `/ ___/ __ / _ \/ __ \
+ / /___/ / / / / ,< | |/ |/ / /_/ / / / /_/ / __/ / / /
+/_____/_/_/ /_/_/|_| |__/|__/\__,_/_/ \__,_/\___/_/ /_/
+
diff --git a/ct/headers/loki b/ct/headers/loki
new file mode 100644
index 000000000..a8e58ae7f
--- /dev/null
+++ b/ct/headers/loki
@@ -0,0 +1,6 @@
+ο»Ώ __ __ _
+ / / ____ / /__(_)
+ / / / __ \/ //_/ /
+ / /___/ /_/ / ,< / /
+/_____/\____/_/|_/_/
+
diff --git a/ct/headers/manyfold b/ct/headers/manyfold
new file mode 100644
index 000000000..b27653eb0
--- /dev/null
+++ b/ct/headers/manyfold
@@ -0,0 +1,6 @@
+ο»Ώ __ ___ ____ __ __
+ / |/ /___ _____ __ __/ __/___ / /___/ /
+ / /|_/ / __ `/ __ \/ / / / /_/ __ \/ / __ /
+ / / / / /_/ / / / / /_/ / __/ /_/ / / /_/ /
+/_/ /_/\__,_/_/ /_/\__, /_/ \____/_/\__,_/
+ /____/
diff --git a/ct/headers/mealie b/ct/headers/mealie
deleted file mode 100644
index a5d36d54c..000000000
--- a/ct/headers/mealie
+++ /dev/null
@@ -1,6 +0,0 @@
- __ ___ ___
- / |/ /__ ____ _/ (_)__
- / /|_/ / _ \/ __ `/ / / _ \
- / / / / __/ /_/ / / / __/
-/_/ /_/\___/\__,_/_/_/\___/
-
diff --git a/ct/headers/metabase b/ct/headers/metabase
deleted file mode 100644
index a98c3c699..000000000
--- a/ct/headers/metabase
+++ /dev/null
@@ -1,6 +0,0 @@
- __ ___ __ __
- / |/ /__ / /_____ _/ /_ ____ _________
- / /|_/ / _ \/ __/ __ `/ __ \/ __ `/ ___/ _ \
- / / / / __/ /_/ /_/ / /_/ / /_/ (__ ) __/
-/_/ /_/\___/\__/\__,_/_.___/\__,_/____/\___/
-
diff --git a/ct/headers/minthcm b/ct/headers/minthcm
new file mode 100644
index 000000000..27a85fbb5
--- /dev/null
+++ b/ct/headers/minthcm
@@ -0,0 +1,6 @@
+ο»Ώ __ ____ __ __ __________ ___
+ / |/ (_)___ / /_/ / / / ____/ |/ /
+ / /|_/ / / __ \/ __/ /_/ / / / /|_/ /
+ / / / / / / / / /_/ __ / /___/ / / /
+/_/ /_/_/_/ /_/\__/_/ /_/\____/_/ /_/
+
diff --git a/ct/headers/netbird b/ct/headers/netbird
new file mode 100644
index 000000000..22e179ef1
--- /dev/null
+++ b/ct/headers/netbird
@@ -0,0 +1,6 @@
+ο»Ώ _ __ __ ____ _ __
+ / | / /__ / /_/ __ )(_)________/ /
+ / |/ / _ \/ __/ __ / / ___/ __ /
+ / /| / __/ /_/ /_/ / / / / /_/ /
+/_/ |_/\___/\__/_____/_/_/ \__,_/
+
diff --git a/ct/headers/nextexplorer b/ct/headers/nextexplorer
new file mode 100644
index 000000000..c260c4832
--- /dev/null
+++ b/ct/headers/nextexplorer
@@ -0,0 +1,6 @@
+ο»Ώ __ ______ __
+ ____ ___ _ __/ /_/ ____/ ______ / /___ ________ _____
+ / __ \/ _ \| |/_/ __/ __/ | |/_/ __ \/ / __ \/ ___/ _ \/ ___/
+ / / / / __/> /_/ /____> /_/ / / /_/ / / / __/ /
+/_/ /_/\___/_/|_|\__/_____/_/|_/ .___/_/\____/_/ \___/_/
+ /_/
diff --git a/ct/headers/opencloud b/ct/headers/opencloud
new file mode 100644
index 000000000..c8dff8968
--- /dev/null
+++ b/ct/headers/opencloud
@@ -0,0 +1,6 @@
+ο»Ώ ____ ________ __
+ / __ \____ ___ ____ / ____/ /___ __ ______/ /
+ / / / / __ \/ _ \/ __ \/ / / / __ \/ / / / __ /
+/ /_/ / /_/ / __/ / / / /___/ / /_/ / /_/ / /_/ /
+\____/ .___/\___/_/ /_/\____/_/\____/\__,_/\__,_/
+ /_/
diff --git a/ct/headers/openeuler b/ct/headers/openeuler
new file mode 100644
index 000000000..e5b7813ae
--- /dev/null
+++ b/ct/headers/openeuler
@@ -0,0 +1,6 @@
+ο»Ώ ______ __
+ ____ ____ ___ ____ / ____/_ __/ /__ _____
+ / __ \/ __ \/ _ \/ __ \/ __/ / / / / / _ \/ ___/
+/ /_/ / /_/ / __/ / / / /___/ /_/ / / __/ /
+\____/ .___/\___/_/ /_/_____/\__,_/_/\___/_/
+ /_/
diff --git a/ct/headers/opensuse b/ct/headers/opensuse
new file mode 100644
index 000000000..d6468bce1
--- /dev/null
+++ b/ct/headers/opensuse
@@ -0,0 +1,6 @@
+ο»Ώ _____ __ _______ ______
+ ____ ____ ___ ____ / ___// / / / ___// ____/
+ / __ \/ __ \/ _ \/ __ \\__ \/ / / /\__ \/ __/
+/ /_/ / /_/ / __/ / / /__/ / /_/ /___/ / /___
+\____/ .___/\___/_/ /_/____/\____//____/_____/
+ /_/
diff --git a/ct/headers/papra b/ct/headers/papra
new file mode 100644
index 000000000..c05106056
--- /dev/null
+++ b/ct/headers/papra
@@ -0,0 +1,6 @@
+ο»Ώ ____
+ / __ \____ _____ _________ _
+ / /_/ / __ `/ __ \/ ___/ __ `/
+ / ____/ /_/ / /_/ / / / /_/ /
+/_/ \__,_/ .___/_/ \__,_/
+ /_/
diff --git a/ct/headers/petio b/ct/headers/petio
index d8deb745a..14e80a73c 100644
--- a/ct/headers/petio
+++ b/ct/headers/petio
@@ -1,4 +1,4 @@
- ____ __ _
+ο»Ώ ____ __ _
/ __ \___ / /_(_)___
/ /_/ / _ \/ __/ / __ \
/ ____/ __/ /_/ / /_/ /
diff --git a/ct/headers/piler b/ct/headers/piler
new file mode 100644
index 000000000..7d068c9ad
--- /dev/null
+++ b/ct/headers/piler
@@ -0,0 +1,6 @@
+ο»Ώ ____ _ __
+ / __ \(_) /__ _____
+ / /_/ / / / _ \/ ___/
+ / ____/ / / __/ /
+/_/ /_/_/\___/_/
+
diff --git a/ct/headers/pixelfed b/ct/headers/pixelfed
new file mode 100644
index 000000000..094d745d7
--- /dev/null
+++ b/ct/headers/pixelfed
@@ -0,0 +1,6 @@
+ο»Ώ ____ _ ______ __
+ / __ \(_) _____ / / __/__ ____/ /
+ / /_/ / / |/_/ _ \/ / /_/ _ \/ __ /
+ / ____/ /> __/ / __/ __/ /_/ /
+/_/ /_/_/|_|\___/_/_/ \___/\__,_/
+
diff --git a/ct/headers/plex b/ct/headers/plex
new file mode 100644
index 000000000..c62258f84
--- /dev/null
+++ b/ct/headers/plex
@@ -0,0 +1,6 @@
+ο»Ώ ____ __
+ / __ \/ /__ _ __
+ / /_/ / / _ \| |/_/
+ / ____/ / __/> <
+/_/ /_/\___/_/|_|
+
diff --git a/ct/headers/plex2 b/ct/headers/plex2
new file mode 100644
index 000000000..5381e8d73
--- /dev/null
+++ b/ct/headers/plex2
@@ -0,0 +1,6 @@
+ο»Ώ ____ __ ___
+ / __ \/ /__ _ _|__ \
+ / /_/ / / _ \| |/_/_/ /
+ / ____/ / __/> __/
+/_/ /_/\___/_/|_/____/
+
diff --git a/ct/headers/postgresus b/ct/headers/postgresus
new file mode 100644
index 000000000..cb472d558
--- /dev/null
+++ b/ct/headers/postgresus
@@ -0,0 +1,6 @@
+ο»Ώ ____ __
+ / __ \____ _____/ /_____ _________ _______ _______
+ / /_/ / __ \/ ___/ __/ __ `/ ___/ _ \/ ___/ / / / ___/
+ / ____/ /_/ (__ ) /_/ /_/ / / / __(__ ) /_/ (__ )
+/_/ \____/____/\__/\__, /_/ \___/____/\__,_/____/
+ /____/
diff --git a/ct/headers/qdrant b/ct/headers/qdrant
deleted file mode 100644
index f6a89dbc3..000000000
--- a/ct/headers/qdrant
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ __ __
- / __ \____/ /________ _____ / /_
- / / / / __ / ___/ __ `/ __ \/ __/
-/ /_/ / /_/ / / / /_/ / / / / /_
-\___\_\__,_/_/ \__,_/_/ /_/\__/
-
diff --git a/ct/headers/qui b/ct/headers/qui
new file mode 100644
index 000000000..1f3048cf7
--- /dev/null
+++ b/ct/headers/qui
@@ -0,0 +1,6 @@
+ο»Ώ ____ _
+ / __ \__ __(_)
+ / / / / / / / /
+/ /_/ / /_/ / /
+\___\_\__,_/_/
+
diff --git a/ct/headers/rockylinux b/ct/headers/rockylinux
new file mode 100644
index 000000000..4168b5004
--- /dev/null
+++ b/ct/headers/rockylinux
@@ -0,0 +1,6 @@
+ο»Ώ ____ __ __ _
+ / __ \____ _____/ /____ __ / / (_)___ __ ___ __
+ / /_/ / __ \/ ___/ //_/ / / / / / / / __ \/ / / / |/_/
+ / _, _/ /_/ / /__/ ,< / /_/ / / /___/ / / / / /_/ /> <
+/_/ |_|\____/\___/_/|_|\__, / /_____/_/_/ /_/\__,_/_/|_|
+ /____/
diff --git a/ct/headers/romm b/ct/headers/romm
index 7f214d48e..3e942aefb 100644
--- a/ct/headers/romm
+++ b/ct/headers/romm
@@ -1,4 +1,4 @@
- ____ __ ___
+ο»Ώ ____ __ ___
/ __ \____ ____ ___ / |/ /
/ /_/ / __ \/ __ `__ \/ /|_/ /
/ _, _/ /_/ / / / / / / / / /
diff --git a/ct/headers/rustypaste b/ct/headers/rustypaste
new file mode 100644
index 000000000..c691b0a30
--- /dev/null
+++ b/ct/headers/rustypaste
@@ -0,0 +1,6 @@
+ο»Ώ __ __
+ _______ _______/ /___ ______ ____ ______/ /____
+ / ___/ / / / ___/ __/ / / / __ \/ __ `/ ___/ __/ _ \
+ / / / /_/ (__ ) /_/ /_/ / /_/ / /_/ (__ ) /_/ __/
+/_/ \__,_/____/\__/\__, / .___/\__,_/____/\__/\___/
+ /____/_/
diff --git a/ct/headers/rybbit b/ct/headers/rybbit
index f4726262c..edc36ae6c 100644
--- a/ct/headers/rybbit
+++ b/ct/headers/rybbit
@@ -1,4 +1,4 @@
- ____ __ __ _ __
+ο»Ώ ____ __ __ _ __
/ __ \__ __/ /_ / /_ (_) /_
/ /_/ / / / / __ \/ __ \/ / __/
/ _, _/ /_/ / /_/ / /_/ / / /_
diff --git a/ct/headers/snowshare b/ct/headers/snowshare
deleted file mode 100644
index 160614e0c..000000000
--- a/ct/headers/snowshare
+++ /dev/null
@@ -1,6 +0,0 @@
- _____ _____ __
- / ___/____ ____ _ __/ ___// /_ ____ _________
- \__ \/ __ \/ __ \ | /| / /\__ \/ __ \/ __ `/ ___/ _ \
- ___/ / / / / /_/ / |/ |/ /___/ / / / / /_/ / / / __/
-/____/_/ /_/\____/|__/|__//____/_/ /_/\__,_/_/ \___/
-
diff --git a/ct/headers/tor-snowflake b/ct/headers/tor-snowflake
new file mode 100644
index 000000000..c1e8728d2
--- /dev/null
+++ b/ct/headers/tor-snowflake
@@ -0,0 +1,6 @@
+ο»Ώ __ ______ __
+ / /_____ _____ _________ ____ _ __/ __/ /___ _/ /_____
+ / __/ __ \/ ___/_____/ ___/ __ \/ __ \ | /| / / /_/ / __ `/ //_/ _ \
+/ /_/ /_/ / / /_____(__ ) / / / /_/ / |/ |/ / __/ / /_/ / ,< / __/
+\__/\____/_/ /____/_/ /_/\____/|__/|__/_/ /_/\__,_/_/|_|\___/
+
diff --git a/ct/headers/tracearr b/ct/headers/tracearr
new file mode 100644
index 000000000..aee118c88
--- /dev/null
+++ b/ct/headers/tracearr
@@ -0,0 +1,6 @@
+ο»Ώ ______
+ /_ __/________ _________ ____ ___________
+ / / / ___/ __ `/ ___/ _ \/ __ `/ ___/ ___/
+ / / / / / /_/ / /__/ __/ /_/ / / / /
+/_/ /_/ \__,_/\___/\___/\__,_/_/ /_/
+
diff --git a/ct/headers/transmission-openvpn b/ct/headers/transmission-openvpn
index 3c6830b05..372fb12b4 100644
--- a/ct/headers/transmission-openvpn
+++ b/ct/headers/transmission-openvpn
@@ -1,4 +1,4 @@
- __ _ _
+ο»Ώ __ _ _
/ /__________ _____ _________ ___ (_)_________(_)___ ____ ____ ____ ___ ____ _ ______ ____
/ __/ ___/ __ `/ __ \/ ___/ __ `__ \/ / ___/ ___/ / __ \/ __ \______/ __ \/ __ \/ _ \/ __ \ | / / __ \/ __ \
/ /_/ / / /_/ / / / (__ ) / / / / / (__ |__ ) / /_/ / / / /_____/ /_/ / /_/ / __/ / / / |/ / /_/ / / / /
diff --git a/ct/headers/ubuntu b/ct/headers/ubuntu
index a4b0eebf9..8c8a9f69f 100644
--- a/ct/headers/ubuntu
+++ b/ct/headers/ubuntu
@@ -1,4 +1,4 @@
- __ ____ __
+ο»Ώ __ ____ __
/ / / / /_ __ ______ / /___ __
/ / / / __ \/ / / / __ \/ __/ / / /
/ /_/ / /_/ / /_/ / / / / /_/ /_/ /
diff --git a/ct/headers/viseron b/ct/headers/viseron
deleted file mode 100644
index 8cb594daf..000000000
--- a/ct/headers/viseron
+++ /dev/null
@@ -1,6 +0,0 @@
- _ ___
-| | / (_)_______ _________ ____
-| | / / / ___/ _ \/ ___/ __ \/ __ \
-| |/ / (__ ) __/ / / /_/ / / / /
-|___/_/____/\___/_/ \____/_/ /_/
-
diff --git a/ct/headers/wanderer b/ct/headers/wanderer
deleted file mode 100644
index 80a6ccbf2..000000000
--- a/ct/headers/wanderer
+++ /dev/null
@@ -1,6 +0,0 @@
- _ __ __
-| | / /___ _____ ____/ /__ ________ _____
-| | /| / / __ `/ __ \/ __ / _ \/ ___/ _ \/ ___/
-| |/ |/ / /_/ / / / / /_/ / __/ / / __/ /
-|__/|__/\__,_/_/ /_/\__,_/\___/_/ \___/_/
-
diff --git a/ct/headers/web-check b/ct/headers/web-check
deleted file mode 100644
index 371062cb9..000000000
--- a/ct/headers/web-check
+++ /dev/null
@@ -1,6 +0,0 @@
- __ __ __
- _ _____ / /_ _____/ /_ ___ _____/ /__
-| | /| / / _ \/ __ \______/ ___/ __ \/ _ \/ ___/ //_/
-| |/ |/ / __/ /_/ /_____/ /__/ / / / __/ /__/ ,<
-|__/|__/\___/_.___/ \___/_/ /_/\___/\___/_/|_|
-
diff --git a/ct/headers/wishlist b/ct/headers/wishlist
new file mode 100644
index 000000000..a55ad71bc
--- /dev/null
+++ b/ct/headers/wishlist
@@ -0,0 +1,6 @@
+ο»Ώ _ ___ __ ___ __
+| | / (_)____/ /_ / (_)____/ /_
+| | /| / / / ___/ __ \/ / / ___/ __/
+| |/ |/ / (__ ) / / / / (__ ) /_
+|__/|__/_/____/_/ /_/_/_/____/\__/
+
diff --git a/ct/headers/yubal b/ct/headers/yubal
new file mode 100644
index 000000000..700a03f72
--- /dev/null
+++ b/ct/headers/yubal
@@ -0,0 +1,6 @@
+ο»Ώ__ __ __ __
+\ \/ /_ __/ /_ ____ _/ /
+ \ / / / / __ \/ __ `/ /
+ / / /_/ / /_/ / /_/ / /
+/_/\__,_/_.___/\__,_/_/
+
diff --git a/ct/heimdall-dashboard.sh b/ct/heimdall-dashboard.sh
deleted file mode 100644
index c4fc9349a..000000000
--- a/ct/heimdall-dashboard.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://heimdall.site/
-
-APP="Heimdall-Dashboard"
-var_tags="${var_tags:-dashboard}"
-var_cpu="${var_cpu:-1}"
-var_ram="${var_ram:-512}"
-var_disk="${var_disk:-2}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/Heimdall ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "Heimdall" "linuxserver/Heimdall"; then
- msg_info "Stopping Service"
- systemctl stop heimdall
- sleep 1
- msg_ok "Stopped Service"
-
- msg_info "Backing up Data"
- cp -R /opt/Heimdall/database database-backup
- cp -R /opt/Heimdall/public public-backup
- sleep 1
- msg_ok "Backed up Data"
-
- setup_composer
- fetch_and_deploy_gh_release "Heimdall" "linuxserver/Heimdall" "tarball"
-
- msg_info "Updating Heimdall-Dashboard"
- cd /opt/Heimdall
- export COMPOSER_ALLOW_SUPERUSER=1
- $STD composer dump-autoload
- msg_ok "Updated Heimdall-Dashboard"
-
- msg_info "Restoring Data"
- cd ~
- cp -R database-backup/* /opt/Heimdall/database
- cp -R public-backup/* /opt/Heimdall/public
- sleep 1
- msg_ok "Restored Data"
-
- msg_info "Cleaning Up"
- rm -rf {public-backup,database-backup}
- sleep 1
- msg_ok "Cleaned Up"
-
- msg_info "Starting Service"
- systemctl start heimdall.service
- sleep 2
- msg_ok "Started Service"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7990${CL}"
diff --git a/ct/homarr.sh b/ct/homarr.sh
deleted file mode 100644
index 151823f0b..000000000
--- a/ct/homarr.sh
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: CrazyWolf13
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://homarr.dev/
-
-APP="homarr"
-var_tags="${var_tags:-arr;dashboard}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-1024}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/homarr ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "homarr" "Meierschlumpf/homarr"; then
- msg_info "Stopping Services (Patience)"
- systemctl stop homarr
- systemctl stop redis-server
- msg_ok "Services Stopped"
-
-
- if ! { grep -q '^REDIS_IS_EXTERNAL=' /opt/homarr/.env 2>/dev/null || grep -q '^REDIS_IS_EXTERNAL=' /opt/homarr.env 2>/dev/null; }; then
- msg_info "Fixing old structure"
- systemctl disable -q --now nginx
- $STD apt install -y musl-dev
- # Error: ec 15 21:05:23 homarr run.sh[330]: β¨― Error: libc.musl-x86_64.so.1: cannot open shared object file: No such file or di>
- # Dec 15 21:05:23 homarr run.sh[330]: at ignore-listed frames {
- # Dec 15 21:05:23 homarr run.sh[330]: code: 'ERR_DLOPEN_FAILED'
- # Dec 15 21:05:23 homarr run.sh[330]: }
- ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1
- cp /opt/homarr/.env /opt/homarr.env
- echo "REDIS_IS_EXTERNAL='true'" >> /opt/homarr.env
- sed -i 's|^ExecStart=.*|ExecStart=/opt/homarr/run.sh|' /etc/systemd/system/homarr.service
- sed -i 's|^EnvironmentFile=.*|EnvironmentFile=-/opt/homarr.env|' /etc/systemd/system/homarr.service
- chown -R redis:redis /appdata/redis
- chmod 755 /appdata/redis
- mkdir -p /etc/systemd/system/redis-server.service.d/
- cat > /etc/systemd/system/redis-server.service.d/override.conf << 'EOF'
-[Service]
-ReadWritePaths=-/appdata/redis -/var/lib/redis -/var/log/redis -/var/run/redis -/etc/redis
-EOF
- systemctl daemon-reload
- rm /opt/run_homarr.sh
- msg_ok "Fixed old structure"
- fi
-
- msg_info "Updating Nodejs"
- $STD apt update
- $STD apt upgrade nodejs -y
- msg_ok "Updated Nodejs"
-
- NODE_VERSION=$(curl -s https://raw.githubusercontent.com/Meierschlumpf/homarr/dev/package.json | jq -r '.engines.node | split(">=")[1] | split(".")[0]')
- setup_nodejs
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "homarr" "Meierschlumpf/homarr" "prebuild" "latest" "/opt/homarr" "source-amd64.tar.gz"
-
- msg_info "Updating Homarr"
- cp /opt/homarr/redis.conf /etc/redis/redis.conf
- rm /etc/nginx/nginx.conf
- mkdir -p /etc/nginx/templates
- cp /opt/homarr/nginx.conf /etc/nginx/templates/nginx.conf
- msg_ok "Updated Homarr"
-
- msg_info "Starting Services"
- chmod +x /opt/homarr/run.sh
- systemctl start homarr
- systemctl start redis-server
- msg_ok "Started Services"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7575${CL}"
diff --git a/ct/hoodik.sh b/ct/hoodik.sh
index b692d04f7..f6fb3b526 100644
--- a/ct/hoodik.sh
+++ b/ct/hoodik.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/hudikhq/hoodik
@@ -38,23 +38,23 @@ function update_script() {
cp /opt/hoodik/.env /tmp/hoodik.env.bak
msg_ok "Backed up Configuration"
- msg_info "Updating ${APP} (Patience - this takes 15-20 minutes)"
+ msg_info "Updating Hoodik (Patience - this takes 15-20 minutes)"
source ~/.cargo/env
rm -rf /opt/hoodik
fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "tarball" "latest" "/opt/hoodik"
cd /opt/hoodik
-
+
msg_info "Building Frontend"
$STD yarn install --frozen-lockfile
$STD yarn wasm-pack
$STD yarn web:build
msg_ok "Built Frontend"
-
+
msg_info "Building Backend"
$STD cargo build --release
cp /opt/hoodik/target/release/hoodik /usr/local/bin/hoodik
chmod +x /usr/local/bin/hoodik
- msg_ok "Updated ${APP}"
+ msg_ok "Updated Hoodik"
msg_info "Restoring Configuration"
cp /tmp/hoodik.env.bak /opt/hoodik/.env
@@ -70,7 +70,6 @@ function update_script() {
msg_info "Starting Services"
systemctl start hoodik
msg_ok "Started Services"
-
msg_ok "Updated Successfully"
fi
exit
@@ -80,7 +79,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5443${CL}"
diff --git a/ct/joplin-server.sh b/ct/joplin-server.sh
new file mode 100644
index 000000000..1de7846c9
--- /dev/null
+++ b/ct/joplin-server.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: SlaviΕ‘a AreΕΎina (tremor021)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://joplinapp.org/
+
+APP="Joplin-Server"
+var_tags="${var_tags:-notes}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-6144}"
+var_disk="${var_disk:-20}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/joplin-server ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ NODE_VERSION=24 NODE_MODULE="yarn,npm,pm2" setup_nodejs
+
+ if check_for_gh_release "joplin-server" "laurent22/joplin"; then
+ msg_info "Stopping Services"
+ systemctl stop joplin-server
+ msg_ok "Stopped Services"
+
+ cp /opt/joplin-server/.env /opt
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "joplin-server" "laurent22/joplin" "tarball"
+ mv /opt/.env /opt/joplin-server
+
+ msg_info "Updating Joplin-Server"
+ cd /opt/joplin-server
+ sed -i "/onenote-converter/d" packages/lib/package.json
+ $STD yarn config set --home enableTelemetry 0
+ export BUILD_SEQUENCIAL=1
+ $STD yarn install --inline-builds
+ msg_ok "Updated Joplin-Server"
+
+ msg_info "Starting Services"
+ systemctl start joplin-server
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:22300${CL}"
diff --git a/ct/kitchenowl.sh b/ct/kitchenowl.sh
new file mode 100644
index 000000000..7517980d0
--- /dev/null
+++ b/ct/kitchenowl.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: snazzybean
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/TomBursch/kitchenowl
+
+APP="KitchenOwl"
+var_tags="${var_tags:-food;recipes}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-6}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -d /opt/kitchenowl ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "kitchenowl" "TomBursch/kitchenowl"; then
+ msg_info "Stopping Service"
+ systemctl stop kitchenowl
+ msg_ok "Stopped Service"
+
+ msg_info "Backing up KitchenOwl"
+ mkdir -p /opt/kitchenowl_backup
+ cp -r /opt/kitchenowl/data /opt/kitchenowl_backup/
+ cp -f /opt/kitchenowl/kitchenowl.env /opt/kitchenowl_backup/
+ msg_ok "Backed up KitchenOwl"
+
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "kitchenowl" "TomBursch/kitchenowl" "tarball" "latest" "/opt/kitchenowl"
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "kitchenowl-web" "TomBursch/kitchenowl" "prebuild" "latest" "/opt/kitchenowl/web" "kitchenowl_Web.tar.gz"
+
+ msg_info "Restoring KitchenOwl data"
+ sed -i 's/default=True/default=False/' /opt/kitchenowl/backend/wsgi.py
+ cp -r /opt/kitchenowl_backup/data /opt/kitchenowl/
+ cp -f /opt/kitchenowl_backup/kitchenowl.env /opt/kitchenowl/
+ rm -rf /opt/kitchenowl_backup
+ msg_ok "Restored KitchenOwl data"
+
+ msg_info "Updating KitchenOwl"
+ cd /opt/kitchenowl/backend
+ $STD uv sync --frozen
+ cd /opt/kitchenowl/backend
+ set -a
+ source /opt/kitchenowl/kitchenowl.env
+ set +a
+ $STD uv run flask db upgrade
+ msg_ok "Updated KitchenOwl"
+
+ msg_info "Starting Service"
+ systemctl start kitchenowl
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:80${CL}"
diff --git a/ct/loki.sh b/ct/loki.sh
new file mode 100644
index 000000000..fd2df1f1f
--- /dev/null
+++ b/ct/loki.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: hoholms
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/grafana/loki
+
+APP="Loki"
+var_tags="${var_tags:-monitoring;logs}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-512}"
+var_disk="${var_disk:-2}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if ! dpkg -s loki >/dev/null 2>&1; then
+ msg_error "No ${APP} Installation Found!"
+ exit 1
+ fi
+
+ msg_info "Stopping Loki"
+ systemctl stop loki
+ systemctl stop promtail
+ msg_ok "Stopped Loki"
+
+ msg_info "Updating Loki"
+ $STD apt update
+ $STD apt --only-upgrade install -y loki
+ $STD apt --only-upgrade install -y promtail
+ msg_ok "Updated Loki"
+
+ msg_info "Starting Loki"
+ systemctl start loki
+ systemctl start promtail
+ msg_ok "Started Loki"
+ msg_ok "Updated successfully!"
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3100${CL}\n"
+echo -e "${INFO}${YW} Access promtail using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9080${CL}"
diff --git a/ct/mail-archiver.sh b/ct/mail-archiver.sh
deleted file mode 100644
index 2205f301f..000000000
--- a/ct/mail-archiver.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: SlaviΕ‘a AreΕΎina (tremor021)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/s1t5/mail-archiver
-
-APP="Mail-Archiver"
-var_tags="${var_tags:-mail-archiver}"
-var_cpu="${var_cpu:-1}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -d /opt/mail-archiver ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "mail-archiver" "s1t5/mail-archiver"; then
- msg_info "Stopping Mail-Archiver"
- systemctl stop mail-archiver
- msg_ok "Stopped Mail-Archiver"
-
- msg_info "Creating Backup"
- cp /opt/mail-archiver/appsettings.json /opt/mail-archiver/.env /opt/
- [[ -d /opt/mail-archiver/DataProtection-Keys ]] && cp -r /opt/mail-archiver/DataProtection-Keys /opt
- msg_ok "Created Backup"
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "mail-archiver" "s1t5/mail-archiver" "tarball"
-
- msg_info "Updating Mail-Archiver"
- mv /opt/mail-archiver /opt/mail-archiver-build
- cd /opt/mail-archiver-build
- $STD dotnet restore
- $STD dotnet publish -c Release -o /opt/mail-archiver
- rm -rf /opt/mail-archiver-build
- msg_ok "Updated Mail-Archiver"
-
- msg_info "Restoring Backup"
- cp /opt/appsettings.json /opt/.env /opt/mail-archiver
- [[ -d /opt/DataProtection-Keys ]] && cp -r /opt/DataProtection-Keys /opt/mail-archiver/
- msg_ok "Restored Backup"
-
- msg_info "Starting Mail-Archiver"
- systemctl start mail-archiver
- msg_ok "Started Mail-Archiver"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}"
diff --git a/ct/manyfold.sh b/ct/manyfold.sh
new file mode 100644
index 000000000..08ea18617
--- /dev/null
+++ b/ct/manyfold.sh
@@ -0,0 +1,105 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: bvdberg01
+# Co-Author: SunFlowerOwl
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/manyfold3d/manyfold
+
+APP="Manyfold"
+var_tags="${var_tags:-3d}"
+var_cpu="${var_cpu:-4}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-15}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/manyfold ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "manyfold" "manyfold3d/manyfold"; then
+ msg_info "Stopping Service"
+ systemctl stop manyfold.target manyfold-rails.1 manyfold-default_worker.1 manyfold-performance_worker.1
+ msg_ok "Stopped Service"
+
+ msg_info "Backing up data"
+ source /opt/manyfold/.env
+ mv /opt/manyfold/app/storage /opt/manyfold/app/tmp /opt/manyfold/app/config/credentials.yml.enc /opt/manyfold/app/config/master.key ~/
+ $STD tar -cvzf "/opt/manyfold_${APP_VERSION}_backup.tar.gz" /opt/manyfold/app/
+ rm -rf /opt/manyfold/app/
+ msg_ok "Backed-up data"
+
+ fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold/app"
+
+ msg_info "Configuring manyfold environment"
+ RUBY_INSTALL_VERSION=$(cat /opt/manyfold/app/.ruby-version)
+ YARN_VERSION=$(grep '"packageManager":' /opt/manyfold/app/package.json | sed -E 's/.*"(yarn@[0-9\.]+)".*/\1/')
+ RELEASE=$(get_latest_github_release "manyfold3d/manyfold")
+ sed -i "s/^export APP_VERSION=.*/export APP_VERSION=$RELEASE/" "/opt/manyfold/.env"
+ cat </opt/manyfold/user_setup.sh
+#!/bin/bash
+
+source /opt/manyfold/.env
+export PATH="/home/manyfold/.rbenv/bin:\$PATH"
+eval "\$(/home/manyfold/.rbenv/bin/rbenv init - bash)"
+cd /opt/manyfold/app
+rbenv global $RUBY_INSTALL_VERSION
+gem install bundler
+bundle install
+gem install sidekiq
+gem install foreman
+corepack enable yarn
+corepack prepare $YARN_VERSION --activate
+corepack use $YARN_VERSION
+bin/rails db:migrate
+bin/rails assets:precompile
+EOF
+ msg_ok "Configured manyfold environment"
+
+ RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" HOME=/home/manyfold setup_ruby
+
+ msg_info "Installing Manyfold"
+ chown -R manyfold:manyfold /home/manyfold/.rbenv
+ rm -rf /opt/manyfold/app/storage /opt/manyfold/app/tmp /opt/manyfold/app/config/credentials.yml.enc
+ mv ~/storage ~/tmp /opt/manyfold/app/
+ mv ~/credentials.yml.enc ~/master.key /opt/manyfold/app/config/
+ chown -R manyfold:manyfold /opt/manyfold
+ chmod +x /opt/manyfold/user_setup.sh
+ $STD sudo -u manyfold bash /opt/manyfold/user_setup.sh
+ rm -f /opt/manyfold/user_setup.sh
+ msg_ok "Installed manyfold"
+
+ msg_info "Restoring Service"
+ source /opt/manyfold/.env
+ export PATH="/home/manyfold/.rbenv/shims:/home/manyfold/.rbenv/bin:$PATH"
+ $STD foreman export systemd /etc/systemd/system -a manyfold -u manyfold -f /opt/manyfold/app/Procfile
+ for f in /etc/systemd/system/manyfold-*.service; do
+ sed -i "s|/bin/bash -lc '|/bin/bash -lc 'source /opt/manyfold/.env \&\& |" "$f"
+ done
+ systemctl enable -q --now manyfold.target manyfold-rails.1 manyfold-default_worker.1 manyfold-performance_worker.1
+ msg_ok "Restored Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/netbird.sh b/ct/netbird.sh
new file mode 100644
index 000000000..8495258d1
--- /dev/null
+++ b/ct/netbird.sh
@@ -0,0 +1,48 @@
+#!/usr/bin/env bash
+
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: TechHutTV
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://netbird.io/
+
+APP="NetBird"
+var_tags="${var_tags:-network;vpn}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-512}"
+var_disk="${var_disk:-4}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+var_tun="${var_tun:-yes}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -f /etc/netbird/config.json ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ msg_info "Updating Netbird"
+ $STD apt update
+ $STD apt upgrade -y
+ msg_ok "Updated successfully!"
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access NetBird by entering the container and running:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}netbird up${CL}"
diff --git a/ct/nextexplorer.sh b/ct/nextexplorer.sh
index 323867052..6b2b651b4 100644
--- a/ct/nextexplorer.sh
+++ b/ct/nextexplorer.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/vikramsoni2/nextExplorer
@@ -68,7 +68,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/nodecast-tv.sh b/ct/nodecast-tv.sh
new file mode 100644
index 000000000..202e65ecc
--- /dev/null
+++ b/ct/nodecast-tv.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: luismco
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/technomancer702/nodecast-tv
+
+APP="nodecast-tv"
+var_tags="${var_tags:-media}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-4}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/nodecast-tv ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "nodecast-tv" "technomancer702/nodecast-tv"; then
+ msg_info "Stopping Service"
+ systemctl stop nodecast-tv
+ msg_ok "Stopped Service"
+
+ fetch_and_deploy_gh_release "nodecast-tv" "technomancer702/nodecast-tv"
+
+ msg_info "Updating Modules"
+ cd /opt/nodecast-tv
+ $STD npm install
+ msg_ok "Updated Modules"
+
+ msg_info "Starting Service"
+ systemctl start nodecast-tv
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
+
diff --git a/ct/opencloud.sh b/ct/opencloud.sh
index 78aadba47..6c047fa6d 100644
--- a/ct/opencloud.sh
+++ b/ct/opencloud.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://opencloud.eu
@@ -29,7 +29,7 @@ function update_script() {
exit
fi
- RELEASE="v4.0.0"
+ RELEASE="v4.1.0"
if check_for_gh_release "opencloud" "opencloud-eu/opencloud" "${RELEASE}"; then
msg_info "Stopping services"
systemctl stop opencloud opencloud-wopi
@@ -37,7 +37,7 @@ function update_script() {
msg_info "Updating packages"
$STD apt-get update
- $STD apt-get dist-upgrade
+ $STD apt-get dist-upgrade -y
msg_ok "Updated packages"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "opencloud" "opencloud-eu/opencloud" "singlefile" "${RELEASE}" "/usr/bin" "opencloud-*-linux-amd64"
@@ -54,7 +54,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}https://${CL}"
diff --git a/ct/openeuler.sh b/ct/openeuler.sh
index 3600739c2..893fd0f9a 100644
--- a/ct/openeuler.sh
+++ b/ct/openeuler.sh
@@ -1,10 +1,14 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.openeuler.org/
+# NOTE: openEuler has a PVE compatibility issue
+# PVE's post_create_hook expects /etc/redhat-release which openEuler doesn't have by default
+# We handle this in build.func by creating the file after container creation
+
APP="openEuler"
var_tags="${var_tags:-os}"
var_cpu="${var_cpu:-1}"
@@ -27,9 +31,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating OpenEuler LXC"
$STD dnf -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated OpenEuler LXC"
+ msg_ok "Updated successfully!"
exit
}
@@ -37,5 +42,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!\n"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/opensuse.sh b/ct/opensuse.sh
index 08b45460f..94cf4043d 100644
--- a/ct/opensuse.sh
+++ b/ct/opensuse.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.opensuse.org/
@@ -27,9 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating OpenSUSE LXC"
$STD zypper -n update
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated OpenSUSE LXC"
+ msg_ok "Updated successfully!"
exit
}
@@ -37,5 +38,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!\n"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/papra.sh b/ct/papra.sh
new file mode 100644
index 000000000..29c11adc1
--- /dev/null
+++ b/ct/papra.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/papra-hq/papra
+
+APP="Papra"
+var_tags="${var_tags:-document-management}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-10}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/papra ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ RELEASE=$(curl -fsSL https://api.github.com/repos/papra-hq/papra/releases | grep -oP '"tag_name":\s*"\K@papra/docker@[^"]+' | head -n1)
+ if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt 2>/dev/null)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
+ msg_info "Stopping Service"
+ systemctl stop papra
+ msg_ok "Stopped Service"
+
+ msg_info "Updating ${APP} to ${RELEASE}"
+ cd /opt/papra
+ fetch_and_deploy_gh_release "papra" "papra-hq/papra" "tarball" "${RELEASE}" "/opt/papra"
+ $STD pnpm install --frozen-lockfile
+ $STD pnpm --filter "@papra/app-client..." run build
+ $STD pnpm --filter "@papra/app-server..." run build
+ echo "${RELEASE}" >/opt/${APP}_version.txt
+ msg_ok "Updated ${APP} to ${RELEASE}"
+
+ msg_info "Starting Service"
+ systemctl start papra
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ else
+ msg_ok "No update required. ${APP} is already at ${RELEASE}"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:1221${CL}"
diff --git a/ct/piler.sh b/ct/piler.sh
index e592f2e3f..c549f94fa 100644
--- a/ct/piler.sh
+++ b/ct/piler.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.mailpiler.org/
@@ -10,8 +10,8 @@ var_tags="${var_tags:-email;archive;smtp}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-12}"
+var_os="${var_os:-ubuntu}"
+var_version="${var_version:-24.04}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -29,10 +29,7 @@ function update_script() {
exit
fi
- RELEASE_NEW=$(curl -fsSL https://www.mailpiler.org/download.php | grep -oP 'piler-\K[0-9]+\.[0-9]+\.[0-9]+' | head -1)
- RELEASE_OLD=$(pilerd -v 2>/dev/null | grep -oP 'version \K[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown")
-
- if [[ "${RELEASE_NEW}" != "${RELEASE_OLD}" ]]; then
+ if check_for_gh_release "piler" "jsuto/piler"; then
msg_info "Stopping Piler Services"
$STD systemctl stop piler
$STD systemctl stop manticore
@@ -40,40 +37,29 @@ function update_script() {
msg_info "Backing up Configuration"
cp /etc/piler/piler.conf /tmp/piler.conf.bak
+ cp /var/www/piler/config-site.php /tmp/config-site.php.bak 2>/dev/null || true
msg_ok "Backed up Configuration"
- msg_info "Updating to v${RELEASE_NEW}"
+ msg_info "Updating ${APP}"
cd /tmp
- curl -fsSL "https://bitbucket.org/jsuto/piler/downloads/piler-${RELEASE_NEW}.tar.gz" -o piler.tar.gz
- tar -xzf piler.tar.gz
- cd "piler-${RELEASE_NEW}"
-
- $STD ./configure \
- --localstatedir=/var \
- --with-database=mysql \
- --sysconfdir=/etc/piler \
- --enable-memcached
-
- $STD make
- $STD make install
- $STD ldconfig
-
- cd /tmp && rm -rf "piler-${RELEASE_NEW}" piler.tar.gz
- msg_ok "Updated to v${RELEASE_NEW}"
+ fetch_and_deploy_gh_release "piler" "jsuto/piler" "binary" "latest" "/tmp" "piler_*-noble-*_amd64.deb"
+ fetch_and_deploy_gh_release "piler-webui" "jsuto/piler" "binary" "latest" "/tmp" "piler-webui_*-noble-*_amd64.deb"
+ $STD apt-get -f install -y
+ msg_ok "Updated ${APP}"
msg_info "Restoring Configuration"
cp /tmp/piler.conf.bak /etc/piler/piler.conf
- rm -f /tmp/piler.conf.bak
+ [[ -f /tmp/config-site.php.bak ]] && cp /tmp/config-site.php.bak /var/www/piler/config-site.php
+ rm -f /tmp/piler.conf.bak /tmp/config-site.php.bak
chown piler:piler /etc/piler/piler.conf
+ chown -R piler:piler /var/www/piler 2>/dev/null || true
msg_ok "Restored Configuration"
- msg_info "Starting Piler Services"
+ msg_info "Starting Services"
$STD systemctl start manticore
$STD systemctl start piler
- msg_ok "Started Piler Services"
- msg_ok "Updated Successfully to v${RELEASE_NEW}"
- else
- msg_ok "No update available (current: v${RELEASE_OLD})"
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
fi
exit
}
@@ -82,7 +68,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/pixelfed.sh b/ct/pixelfed.sh
index aa93359d1..30581a249 100644
--- a/ct/pixelfed.sh
+++ b/ct/pixelfed.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://pixelfed.org/
@@ -61,7 +61,7 @@ function update_script() {
msg_info "Starting Services"
systemctl start pixelfed-horizon pixelfed-scheduler.timer
msg_ok "Services started"
- msg_ok "Updated Successfully"
+ msg_ok "Updated successfully!"
fi
exit
}
@@ -70,7 +70,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/plex.sh b/ct/plex.sh
deleted file mode 100644
index be50ac0aa..000000000
--- a/ct/plex.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.plex.tv/
-
-APP="Plex"
-var_tags="${var_tags:-media}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-ubuntu}"
-var_version="${var_version:-24.04}"
-var_unprivileged="${var_unprivileged:-1}"
-var_gpu="${var_gpu:-yes}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] &&
- [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select \nplexupdate info >> https://github.com/mrworf/plexupdate" 10 59 2 \
- "1" "Update LXC" ON \
- "2" "Install plexupdate" OFF \
- 3>&1 1>&2 2>&3)
- if [ "$UPD" == "1" ]; then
- msg_info "Updating ${APP} LXC"
- $STD apt update
- $STD apt -y upgrade
- msg_ok "Updated ${APP} LXC"
- msg_ok "Updated successfully!"
- exit
- fi
- if [ "$UPD" == "2" ]; then
- set +e
- bash -c "$(curl -fsSL https://raw.githubusercontent.com/mrworf/plexupdate/master/extras/installer.sh)"
- msg_ok "Updated successfully!"
- exit
- fi
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:32400/web${CL}"
diff --git a/ct/plex2.sh b/ct/plex2.sh
deleted file mode 100644
index 4d925f420..000000000
--- a/ct/plex2.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.plex.tv/
-
-APP="Plex2"
-var_tags="${var_tags:-media}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-ubuntu}"
-var_version="${var_version:-24.04}"
-var_unprivileged="${var_unprivileged:-1}"
-var_gpu="${var_gpu:-yes}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] &&
- [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select \nplexupdate info >> https://github.com/mrworf/plexupdate" 10 59 2 \
- "1" "Update LXC" ON \
- "2" "Install plexupdate" OFF \
- 3>&1 1>&2 2>&3)
- if [ "$UPD" == "1" ]; then
- msg_info "Updating ${APP} LXC"
- $STD apt update
- $STD apt -y upgrade
- msg_ok "Updated ${APP} LXC"
- msg_ok "Updated successfully!"
- exit
- fi
- if [ "$UPD" == "2" ]; then
- set +e
- bash -c "$(curl -fsSL https://raw.githubusercontent.com/mrworf/plexupdate/master/extras/installer.sh)"
- msg_ok "Updated successfully!"
- exit
- fi
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:32400/web${CL}"
diff --git a/ct/postgresus.sh b/ct/postgresus.sh
deleted file mode 100644
index a726e79f5..000000000
--- a/ct/postgresus.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: MickLesk (CanbiZ)
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://github.com/RostislavDugin/postgresus
-
-APP="Postgresus"
-var_tags="${var_tags:-backup;postgresql;database}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -f /opt/postgresus/postgresus ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "RostislavDugin" "postgresus"; then
- msg_info "Stopping Postgresus"
- $STD systemctl stop postgresus
- msg_ok "Stopped Postgresus"
-
- msg_info "Backing up Configuration"
- cp /opt/postgresus/.env /tmp/postgresus.env.bak
- msg_ok "Backed up Configuration"
-
- fetch_and_deploy_gh_release "postgresus" "RostislavDugin/postgresus" "tarball" "v${RELEASE}" "/opt/postgresus"
-
- msg_info "Updating Postgresus"
- cd /opt/postgresus/frontend
- $STD npm ci
- $STD npm run build
- cd /opt/postgresus/backend
- $STD go mod download
- $STD go build -o ../postgresus ./cmd/main.go
- cd /opt/postgresus/
- cp -r frontend/dist ui
- cp -r backend/migrations .
- msg_ok "Updated Postgresus"
-
- msg_info "Restoring Configuration"
- cp /tmp/postgresus.env.bak /opt/postgresus/.env
- rm -f /tmp/postgresus.env.bak
- msg_ok "Restored Configuration"
-
- msg_info "Starting Postgresus"
- $STD systemctl start postgresus
- msg_ok "Started Postgresus"
- msg_ok "Updated successfully!"
- fi
- exit
-}
-
-start
-build_container
-description
-
-msg_ok "Completed Successfully!\n"
-echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
-echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/qui.sh b/ct/qui.sh
new file mode 100644
index 000000000..4984e1b7a
--- /dev/null
+++ b/ct/qui.sh
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (Canbiz)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/autobrr/qui
+
+APP="Qui"
+var_tags="${var_tags:-torrent}"
+var_disk="${var_disk:-10}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-1024}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -f /usr/local/bin/qui ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ if check_for_gh_release "Qui" "autobrr/qui"; then
+ msg_info "Stopping Service"
+ systemctl stop qui
+ msg_ok "Stopped Service"
+
+ fetch_and_deploy_gh_release "qui" "autobrr/qui" "prebuild" "latest" "/tmp/qui" "qui_*_linux_x86_64.tar.gz"
+
+ msg_info "Updating qui"
+ mv /tmp/qui/qui /usr/local/bin/qui
+ chmod +x /usr/local/bin/qui
+ rm -rf /tmp/qui
+ msg_ok "Updated qui"
+
+ msg_info "Starting Service"
+ systemctl start qui
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:7476${CL}"
diff --git a/ct/rockylinux.sh b/ct/rockylinux.sh
index 5cbd26ee0..24ff57599 100644
--- a/ct/rockylinux.sh
+++ b/ct/rockylinux.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://rockylinux.org/
@@ -27,9 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating $APP LXC"
+ msg_info "Updating Rocky Linux LXC"
$STD dnf -y upgrade
- msg_ok "Updated $APP LXC"
+ msg_ok "Updated Rocky Linux LXC"
+ msg_ok "Completed successfully!"
exit
}
@@ -37,5 +38,5 @@ start
build_container
description
-msg_ok "Completed Successfully!"
+msg_ok "Completed successfully!\n"
msg_custom "π" "${GN}" "${APP} setup has been successfully initialized!"
diff --git a/ct/romm.sh b/ct/romm.sh
index 129da9a34..3d9c37a1b 100644
--- a/ct/romm.sh
+++ b/ct/romm.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
+# Co-author: AlphaLawless
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://romm.app
@@ -10,10 +11,9 @@ var_tags="${var_tags:-emulation}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
-var_os="${var_os:-ubuntu}"
-var_version="${var_version:-24.04}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
-var_fuse="${var_fuse:-1}"
header_info "$APP"
variables
@@ -30,35 +30,43 @@ function update_script() {
exit
fi
- msg_info "Stopping $APP"
- systemctl stop romm
- systemctl stop nginx
- msg_ok "Stopped $APP"
+ if check_for_gh_release "romm" "rommapp/romm"; then
+ msg_info "Stopping Services"
+ systemctl stop romm-backend romm-worker romm-scheduler romm-watcher
+ msg_ok "Stopped Services"
- msg_info "Updating $APP"
- cd /opt/romm/app
- git pull
+ msg_info "Backing up configuration"
+ cp /opt/romm/.env /opt/romm/.env.backup
+ msg_ok "Backed up configuration"
- # Update backend
- cd /opt/romm/app
- source /opt/romm/venv/bin/activate
- pip install --upgrade pip
- pip install poetry
- poetry install
+ msg_info "Updating ROMM"
+ fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm"
- # Update frontend
- cd /opt/romm/app/frontend
- npm install
- npm run build
+ cp /opt/romm/.env.backup /opt/romm/.env
- echo "Updated on $(date)" >/opt/romm/version.txt
- msg_ok "Updated $APP"
+ cd /opt/romm
+ $STD uv sync --all-extras
- msg_info "Starting $APP"
- systemctl start romm
- systemctl start nginx
- msg_ok "Started $APP"
- msg_ok "Update Successful"
+ cd /opt/romm/backend
+ $STD uv run alembic upgrade head
+
+ cd /opt/romm/frontend
+ $STD npm install
+ $STD npm run build
+
+ # Merge static assets into dist folder
+ cp -rf /opt/romm/frontend/assets/* /opt/romm/frontend/dist/assets/
+
+ mkdir -p /opt/romm/frontend/dist/assets/romm
+ ln -sfn /var/lib/romm/resources /opt/romm/frontend/dist/assets/romm/resources
+ ln -sfn /var/lib/romm/assets /opt/romm/frontend/dist/assets/romm/assets
+ msg_ok "Updated ROMM"
+
+ msg_info "Starting Services"
+ systemctl start romm-backend romm-worker romm-scheduler romm-watcher
+ msg_ok "Started Services"
+ msg_ok "Updated successfully"
+ fi
exit
}
@@ -66,7 +74,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/ct/rustypaste.sh b/ct/rustypaste.sh
new file mode 100644
index 000000000..a4f1bb6da
--- /dev/null
+++ b/ct/rustypaste.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: GoldenSpringness
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/orhun/rustypaste
+
+APP="rustypaste"
+var_tags="${var_tags:-pastebin;storage}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-1024}"
+var_disk="${var_disk:-20}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -f "/opt/rustypaste/target/release/rustypaste" ]]; then
+ msg_error "No rustypaste Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "rustypaste" "orhun/rustypaste"; then
+ msg_info "Stopping Services"
+ systemctl stop rustypaste
+ msg_ok "Stopped Services"
+
+ msg_info "Creating Backup"
+ tar -czf "/opt/rustypaste_backup_$(date +%F).tar.gz" "/opt/rustypaste/upload"
+ msg_ok "Backup Created"
+
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "tarball" "latest" "/opt/rustypaste"
+
+ msg_info "Updating rustypaste"
+ cd /opt/rustypaste
+ sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml
+ $STD cargo build --locked --release
+ msg_ok "Updated rustypaste"
+
+ msg_info "Starting Services"
+ systemctl start rustypaste
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}rustypaste setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"
diff --git a/ct/thingsboard.sh b/ct/thingsboard.sh
new file mode 100644
index 000000000..7fadb1892
--- /dev/null
+++ b/ct/thingsboard.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/thingsboard/thingsboard
+
+APP="ThingsBoard"
+var_tags="${var_tags:-iot;platform}"
+var_cpu="${var_cpu:-4}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-10}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /usr/share/thingsboard ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "thingsboard" "thingsboard/thingsboard"; then
+ msg_info "Stopping Service"
+ systemctl stop thingsboard
+ msg_ok "Stopped Service"
+
+ fetch_and_deploy_gh_release "thingsboard" "thingsboard/thingsboard" "binary" "latest" "/tmp" "thingsboard-*.deb"
+
+ msg_info "Running Database Upgrade"
+ $STD /usr/share/thingsboard/bin/install/upgrade.sh
+ msg_ok "Database Upgraded"
+
+ msg_info "Starting Service"
+ systemctl start thingsboard
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
diff --git a/ct/tor-snowflake.sh b/ct/tor-snowflake.sh
new file mode 100644
index 000000000..2125380b5
--- /dev/null
+++ b/ct/tor-snowflake.sh
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: KernelSailor
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://snowflake.torproject.org/
+
+APP="tor-snowflake"
+var_tags="${var_tags:-privacy;proxy;tor}"
+var_cpu="${var_cpu:-1}"
+var_ram="${var_ram:-512}"
+var_disk="${var_disk:-4}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+var_nesting="${var_nesting:-0}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ msg_info "Updating Container OS"
+ $STD apt update
+ $STD apt upgrade -y
+ msg_ok "Updated Container OS"
+
+ RELEASE=$(curl -fsSL https://gitlab.torproject.org/api/v4/projects/tpo%2Fanti-censorship%2Fpluggable-transports%2Fsnowflake/releases | jq -r '.[0].tag_name' | sed 's/^v//')
+ if [[ ! -f "~/.tor-snowflake" ]] || [[ "${RELEASE}" != "$(cat "~/.tor-snowflake")" ]]; then
+ msg_info "Stopping Service"
+ systemctl stop snowflake-proxy
+ msg_ok "Stopped Service"
+
+ setup_go
+
+ msg_info "Updating Snowflake"
+ $STD curl -fsSL "https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/archive/v${RELEASE}/snowflake-v${RELEASE}.tar.gz" -o /opt/snowflake.tar.gz
+ $STD tar -xzf /opt/snowflake.tar.gz -C /opt
+ $STD rm -rf /opt/snowflake.tar.gz
+ $STD rm -rf /opt/tor-snowflake
+ $STD mv /opt/snowflake-v${RELEASE} /opt/tor-snowflake
+ $STD chown -R snowflake:snowflake /opt/tor-snowflake
+ $STD sudo -H -u snowflake bash -c "cd /opt/tor-snowflake/proxy && go build -o snowflake-proxy ."
+ echo "${RELEASE}" >~/.tor-snowflake
+ msg_ok "Updated Snowflake to v${RELEASE}"
+
+ msg_info "Starting Service"
+ systemctl start snowflake-proxy
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ else
+ msg_ok "No update required. Snowflake is already at v${RELEASE}."
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
diff --git a/ct/tracearr.sh b/ct/tracearr.sh
new file mode 100644
index 000000000..050477041
--- /dev/null
+++ b/ct/tracearr.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: durzo
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/connorgallopo/Tracearr
+
+APP="Tracearr"
+var_tags="${var_tags:-media}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-5}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -f /etc/systemd/system/tracearr.service ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "tracearr" "connorgallopo/Tracearr"; then
+ msg_info "Stopping Services"
+ systemctl stop tracearr postgresql redis
+ msg_ok "Stopped Services"
+
+ PNPM_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/connorgallopo/Tracearr/refs/heads/main/package.json" | jq -r '.packageManager | split("@")[1]')"
+ NODE_VERSION="22" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tracearr" "connorgallopo/Tracearr" "tarball" "latest" "/opt/tracearr.build"
+
+ msg_info "Building Tracearr"
+ export TZ=$(cat /etc/timezone)
+ cd /opt/tracearr.build
+ $STD pnpm install --frozen-lockfile --force
+ $STD pnpm turbo telemetry disable
+ $STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
+ rm -rf /opt/tracearr
+ mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db}
+ cp -rf package.json /opt/tracearr/
+ cp -rf pnpm-workspace.yaml /opt/tracearr/
+ cp -rf pnpm-lock.yaml /opt/tracearr/
+ cp -rf apps/server/package.json /opt/tracearr/apps/server/
+ cp -rf apps/server/dist /opt/tracearr/apps/server/dist
+ cp -rf apps/web/dist /opt/tracearr/apps/web/dist
+ cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
+ cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
+ cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
+ cp -rf data /opt/tracearr/data
+ mkdir -p /opt/tracearr/data/image-cache
+ rm -rf /opt/tracearr.build
+ cd /opt/tracearr
+ $STD pnpm install --prod --frozen-lockfile --ignore-scripts
+ $STD chown -R tracearr:tracearr /opt/tracearr
+ msg_ok "Built Tracearr"
+
+ msg_info "Configuring Tracearr"
+ sed -i "s/^APP_VERSION=.*/APP_VERSION=$(cat /root/.tracearr)/" /data/tracearr/.env
+ chmod 600 /data/tracearr/.env
+ chown -R tracearr:tracearr /data/tracearr
+ msg_ok "Configured Tracearr"
+
+ msg_info "Starting Services"
+ systemctl start postgresql redis tracearr
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/ubuntu.sh b/ct/ubuntu.sh
index f208d7d09..4f24cd6a0 100644
--- a/ct/ubuntu.sh
+++ b/ct/ubuntu.sh
@@ -1,12 +1,11 @@
#!/usr/bin/env bash
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
# source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/github.func)
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://ubuntu.com/
-echo -e "Loading..."
APP="Ubuntu"
var_tags="${var_tags:-os}"
var_cpu="${var_cpu:-1}"
@@ -29,10 +28,11 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- msg_info "Updating ${APP} LXC"
+ msg_info "Updating Ubuntu LXC"
$STD apt-get update
$STD apt-get -y upgrade
- msg_ok "Updated ${APP} LXC"
+ msg_ok "Updated Ubuntu LXC"
+ msg_ok "Updated successfully!"
exit
}
@@ -40,5 +40,5 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
diff --git a/ct/unifi-os-server.sh b/ct/unifi-os-server.sh
new file mode 100644
index 000000000..610d155a9
--- /dev/null
+++ b/ct/unifi-os-server.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://ui.com/
+
+APP="UniFi-OS-Server"
+var_tags="${var_tags:-network}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-4096}"
+var_disk="${var_disk:-20}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-0}"
+var_tun="${var_tun:-yes}"
+var_nesting="${var_nesting:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -f /usr/local/sbin/unifi-os-server.bin && ! -d /data/unifi ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+ msg_error "UniFi OS Server updates are handled by the UniFi OS app itself."
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:11443${CL}"
diff --git a/ct/wishlist.sh b/ct/wishlist.sh
new file mode 100644
index 000000000..e533463e3
--- /dev/null
+++ b/ct/wishlist.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Dunky13
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/cmintey/wishlist
+
+APP="Wishlist"
+var_tags="${var_tags:-sharing}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-5}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+ if [[ ! -d /opt/wishlist ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "wishlist" "cmintey/wishlist"; then
+ NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs
+
+ msg_info "Stopping Service"
+ systemctl stop wishlist
+ msg_ok "Stopped Service"
+
+ mkdir -p /opt/wishlist-backup
+ cp /opt/wishlist/.env /opt/wishlist-backup/.env
+ cp -a /opt/wishlist/uploads /opt/wishlist-backup
+ cp -a /opt/wishlist/data /opt/wishlist-backup
+
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "wishlist" "cmintey/wishlist" "tarball"
+ LATEST_APP_VERSION=$(get_latest_github_release "cmintey/wishlist" false)
+
+ msg_info "Updating Wishlist"
+ cd /opt/wishlist
+ $STD pnpm install
+ $STD pnpm svelte-kit sync
+ $STD pnpm prisma generate
+ sed -i 's|/usr/src/app/|/opt/wishlist/|g' $(grep -rl '/usr/src/app/' /opt/wishlist)
+ export VERSION="${LATEST_APP_VERSION}"
+ export SHA="${LATEST_APP_VERSION}"
+ $STD pnpm run build
+ $STD pnpm prune --prod
+ chmod +x /opt/wishlist/entrypoint.sh
+ cp /opt/wishlist-backup/.env /opt/wishlist/.env
+ cp -a /opt/wishlist-backup/uploads /opt/wishlist
+ cp -a /opt/wishlist-backup/data /opt/wishlist
+ rm -rf /opt/wishlist-backup
+ msg_ok "Updated Wishlist"
+ msg_info "Starting Service"
+ systemctl start wishlist
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed Successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3280${CL}"
diff --git a/ct/yubal.sh b/ct/yubal.sh
new file mode 100644
index 000000000..8be7de01d
--- /dev/null
+++ b/ct/yubal.sh
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Crazywolf13
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/guillevc/yubal
+
+APP="Yubal"
+var_tags="${var_tags:-music;media}"
+var_cpu="${var_cpu:-2}"
+var_ram="${var_ram:-2048}"
+var_disk="${var_disk:-15}"
+var_os="${var_os:-debian}"
+var_version="${var_version:-13}"
+var_unprivileged="${var_unprivileged:-1}"
+
+header_info "$APP"
+variables
+color
+catch_errors
+
+function update_script() {
+ header_info
+ check_container_storage
+ check_container_resources
+
+ if [[ ! -d /opt/yubal ]]; then
+ msg_error "No ${APP} Installation Found!"
+ exit
+ fi
+
+ if check_for_gh_release "yubal" "guillevc/yubal"; then
+ msg_info "Stopping Services"
+ systemctl stop yubal
+ msg_ok "Stopped Services"
+
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "yubal" "guillevc/yubal" "tarball" "latest" "/opt/yubal"
+
+ msg_info "Building Frontend"
+ cd /opt/yubal/web
+ $STD bun install --frozen-lockfile
+ VERSION=$(get_latest_github_release "guillevc/yubal")
+ VITE_VERSION=$VERSION VITE_COMMIT_SHA=$VERSION VITE_IS_RELEASE=true $STD bun run build
+ msg_ok "Built Frontend"
+
+ msg_info "Installing Python Dependencies"
+ cd /opt/yubal
+ $STD uv sync --no-dev --frozen
+ msg_ok "Installed Python Dependencies"
+
+ msg_info "Starting Services"
+ systemctl start yubal
+ msg_ok "Started Services"
+ msg_ok "Updated successfully!"
+ fi
+ exit
+}
+
+start
+build_container
+description
+
+msg_ok "Completed successfully!\n"
+echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
+echo -e "${INFO}${YW} Access it using the following URL:${CL}"
+echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8000${CL}"
diff --git a/docs/contribution/GUIDE.md b/docs/contribution/GUIDE.md
index 757e86c21..52c4d950f 100644
--- a/docs/contribution/GUIDE.md
+++ b/docs/contribution/GUIDE.md
@@ -310,7 +310,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:PORT${CL}"
@@ -330,7 +330,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:PORT${CL}"
```bash
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT
# Source: https://github.com/example/myapp
@@ -558,7 +558,7 @@ fi
```bash
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# Co-Author: AnotherAuthor (for collaborative work)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/docs/contribution/templates_ct/AppName.md b/docs/contribution/templates_ct/AppName.md
index d334b0c07..8507c7c2d 100644
--- a/docs/contribution/templates_ct/AppName.md
+++ b/docs/contribution/templates_ct/AppName.md
@@ -65,7 +65,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/
Example:
```bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
@@ -266,7 +266,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
diff --git a/docs/contribution/templates_ct/AppName.sh b/docs/contribution/templates_ct/AppName.sh
index 075fc694b..cf9333c4f 100644
--- a/docs/contribution/templates_ct/AppName.sh
+++ b/docs/contribution/templates_ct/AppName.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
@@ -9,7 +9,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/
APP="[APP_NAME]"
# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole"
var_tags="[TAGS]"
-# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
+# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp)
var_cpu="[CPU]"
# Number of cores (1-X) (e.g. 4) - default are 2
var_ram="[RAM]"
@@ -80,7 +80,7 @@ start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:[PORT]${CL}"
diff --git a/docs/contribution/templates_install/AppName-install.md b/docs/contribution/templates_install/AppName-install.md
index 376956d2f..8e23af37f 100644
--- a/docs/contribution/templates_install/AppName-install.md
+++ b/docs/contribution/templates_install/AppName-install.md
@@ -57,7 +57,7 @@
Example:
```bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
diff --git a/docs/contribution/templates_install/AppName-install.sh b/docs/contribution/templates_install/AppName-install.sh
index 01d725dd7..eb573fa32 100644
--- a/docs/contribution/templates_install/AppName-install.sh
+++ b/docs/contribution/templates_install/AppName-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: [YourUserName]
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: [SOURCE_URL]
diff --git a/docs/ct/DETAILED_GUIDE.md b/docs/ct/DETAILED_GUIDE.md
index ba5a00ad3..cd2f8d11d 100644
--- a/docs/ct/DETAILED_GUIDE.md
+++ b/docs/ct/DETAILED_GUIDE.md
@@ -131,7 +131,7 @@ function update_script() { ... } # [10] Update function (optional)
start # [11] Launch container creation
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
```
---
@@ -142,7 +142,7 @@ msg_ok "Completed Successfully!\n"
```bash
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/example/project
@@ -254,7 +254,7 @@ build_container
description
# Display success message
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
@@ -386,7 +386,7 @@ function update_script() {
start
build_container
description
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
```
---
diff --git a/docs/install/DETAILED_GUIDE.md b/docs/install/DETAILED_GUIDE.md
index 0ac4fddb5..8a6912518 100644
--- a/docs/install/DETAILED_GUIDE.md
+++ b/docs/install/DETAILED_GUIDE.md
@@ -85,7 +85,7 @@ RANDOM_UUID # Session UUID for telemetry
#!/usr/bin/env bash # [1] Shebang
# [2] Copyright/Metadata
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT
# Source: https://example.com
@@ -118,7 +118,7 @@ cleanup_lxc
```bash
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourUsername
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/application/repo
diff --git a/frontend/public/json/almalinux.json b/frontend/public/json/almalinux.json
index a6e429706..83d4185fb 100644
--- a/frontend/public/json/almalinux.json
+++ b/frontend/public/json/almalinux.json
@@ -2,7 +2,7 @@
"name": "AlmaLinux",
"slug": "almalinux",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/alpine.json b/frontend/public/json/alpine.json
index c1d24b87f..b23dff382 100644
--- a/frontend/public/json/alpine.json
+++ b/frontend/public/json/alpine.json
@@ -2,7 +2,7 @@
"name": "Alpine Linux",
"slug": "alpine",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/ampache.json b/frontend/public/json/ampache.json
new file mode 100644
index 000000000..d16099011
--- /dev/null
+++ b/frontend/public/json/ampache.json
@@ -0,0 +1,48 @@
+{
+ "name": "Ampache",
+ "slug": "ampache",
+ "categories": [
+ 13
+ ],
+ "date_created": "2026-01-13",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 80,
+ "documentation": "https://github.com/ampache/ampache/wiki",
+ "website": "https://ampache.org/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/ampache.webp",
+ "config_path": "/opt/ampache/config/ampache.cfg.php",
+ "description": "Ampache is a web-based audio streaming application and file manager that allows you to access your music & videos from anywhere. It features a powerful music catalog, multiple user support, transcoding, streaming, and more.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/ampache.sh",
+ "resources": {
+ "cpu": 4,
+ "ram": 2048,
+ "hdd": 5,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "Complete the web-based setup at http://IP/install.php",
+ "type": "info"
+ },
+ {
+ "text": "Database credentials are stored in `~/ampache.creds` - use only the MySQL username and password from this file",
+ "type": "info"
+ },
+ {
+ "text": "During installation, only check 'Create Tables' - leave 'Create Database' and 'Create Database User' unchecked",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/centos.json b/frontend/public/json/centos.json
index 3d9d292e8..976ded699 100644
--- a/frontend/public/json/centos.json
+++ b/frontend/public/json/centos.json
@@ -2,7 +2,7 @@
"name": "CentOS Stream",
"slug": "centos",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/postgresus.json b/frontend/public/json/databasus.json
similarity index 73%
rename from frontend/public/json/postgresus.json
rename to frontend/public/json/databasus.json
index 5d569429a..766d88925 100644
--- a/frontend/public/json/postgresus.json
+++ b/frontend/public/json/databasus.json
@@ -1,24 +1,23 @@
{
- "name": "Postgresus",
- "slug": "postgresus",
+ "name": "Databasus",
+ "slug": "databasus",
"categories": [
- 6,
- 11
+ 7
],
- "date_created": "2025-12-11",
+ "date_created": "2025-01-14",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
- "documentation": "https://github.com/RostislavDugin/postgresus",
- "website": "https://github.com/RostislavDugin/postgresus",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/postgresus.webp",
- "config_path": "/opt/postgresus/.env",
+ "documentation": "https://github.com/databasus/databasus",
+ "website": "https://github.com/databasus/databasus",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/databasus.webp",
+ "config_path": "/opt/databasus/.env",
"description": "Free, open source and self-hosted solution for automated PostgreSQL backups. With multiple storage options, notifications, scheduling, and a beautiful web interface for managing database backups across multiple PostgreSQL instances.",
"install_methods": [
{
"type": "default",
- "script": "ct/postgresus.sh",
+ "script": "ct/databasus.sh",
"resources": {
"cpu": 2,
"ram": 2048,
@@ -30,7 +29,7 @@
],
"default_credentials": {
"username": "admin@localhost",
- "password": "See /root/postgresus.creds"
+ "password": "See /root/databasus.creds"
},
"notes": [
{
diff --git a/frontend/public/json/debian.json b/frontend/public/json/debian.json
index 119315216..a02834425 100644
--- a/frontend/public/json/debian.json
+++ b/frontend/public/json/debian.json
@@ -2,7 +2,7 @@
"name": "Debian",
"slug": "debian",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/devuan.json b/frontend/public/json/devuan.json
index 1681deb21..06b3c96d0 100644
--- a/frontend/public/json/devuan.json
+++ b/frontend/public/json/devuan.json
@@ -2,7 +2,7 @@
"name": "Devuan",
"slug": "devuan",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/ente.json b/frontend/public/json/ente.json
index 2c14b1b4b..91759aa05 100644
--- a/frontend/public/json/ente.json
+++ b/frontend/public/json/ente.json
@@ -2,7 +2,7 @@
"name": "Ente",
"slug": "ente",
"categories": [
- 13
+ 11
],
"date_created": "2025-11-22",
"type": "ct",
diff --git a/frontend/public/json/fedora.json b/frontend/public/json/fedora.json
index f2a65a4c9..15f198bab 100644
--- a/frontend/public/json/fedora.json
+++ b/frontend/public/json/fedora.json
@@ -2,7 +2,7 @@
"name": "Fedora",
"slug": "fedora",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/forgejo-runner.json b/frontend/public/json/forgejo-runner.json
new file mode 100644
index 000000000..1ffd96d0b
--- /dev/null
+++ b/frontend/public/json/forgejo-runner.json
@@ -0,0 +1,35 @@
+{
+ "name": "Forgejo Runner",
+ "slug": "forgejo-runner",
+ "categories": [
+ 20
+ ],
+ "date_created": "2026-01-12",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": null,
+ "documentation": "https://forgejo.org/docs/latest/admin/actions/runner-installation/",
+ "config_path": "/root/.runner",
+ "website": "https://forgejo.org/docs/latest/admin/actions/runner-installation/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/forgejo.webp",
+ "description": "Forgejo Runner is a lightweight service that executes CI/CD jobs for Forgejo, enabling automated builds, tests, and deployments.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/forgejo-runner.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 8,
+ "os": "Debian",
+ "version": "12"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
\ No newline at end of file
diff --git a/frontend/public/json/freepbx.json b/frontend/public/json/freepbx.json
index 768b64d06..601673d5b 100644
--- a/frontend/public/json/freepbx.json
+++ b/frontend/public/json/freepbx.json
@@ -2,7 +2,7 @@
"name": "FreePBX",
"slug": "freepbx",
"categories": [
- 17
+ 0
],
"date_created": "2025-01-15",
"type": "ct",
diff --git a/frontend/public/json/garmin-grafana.json b/frontend/public/json/garmin-grafana.json
index 8c676b733..ee5df81d3 100644
--- a/frontend/public/json/garmin-grafana.json
+++ b/frontend/public/json/garmin-grafana.json
@@ -2,7 +2,7 @@
"name": "garmin-grafana",
"slug": "garmin-grafana",
"categories": [
- 24
+ 9
],
"date_created": "2025-05-08",
"type": "ct",
diff --git a/frontend/public/json/gentoo.json b/frontend/public/json/gentoo.json
index fb08ce247..302dd7607 100644
--- a/frontend/public/json/gentoo.json
+++ b/frontend/public/json/gentoo.json
@@ -2,7 +2,7 @@
"name": "Gentoo",
"slug": "gentoo",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/gwn-manager.json b/frontend/public/json/gwn-manager.json
new file mode 100644
index 000000000..39f0f53ae
--- /dev/null
+++ b/frontend/public/json/gwn-manager.json
@@ -0,0 +1,40 @@
+{
+ "name": "GWN Manager",
+ "slug": "gwn-manager",
+ "categories": [
+ 9
+ ],
+ "date_created": "2025-12-02",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 8443,
+ "documentation": "https://documentation.grandstream.com/article-categories/gwn-mgmt/",
+ "website": "https://www.grandstream.com/products/networking-solutions/wi-fi-management/product/gwn-manager",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/gwn-manager.webp",
+ "config_path": "/gwn/conf/gwn.conf",
+ "description": "GWN Manager is a free on-premise enterprise-grade, management platform for Grandstream GWN series devices. Typically deployed on a customerβs private network, this flexible, scalable solution offers simplified configuration and management.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/gwn-manager.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 6144,
+ "hdd": 8,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "Installation package is pulled from GrandStream website. Installation may take a while.",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/hoodik.json b/frontend/public/json/hoodik.json
index 878c6fe17..65bf673d6 100644
--- a/frontend/public/json/hoodik.json
+++ b/frontend/public/json/hoodik.json
@@ -2,7 +2,7 @@
"name": "Hoodik",
"slug": "hoodik",
"categories": [
- 4
+ 11
],
"date_created": "2025-12-10",
"type": "ct",
diff --git a/frontend/public/json/jellystat.json b/frontend/public/json/jellystat.json
deleted file mode 100644
index f9bf24f0d..000000000
--- a/frontend/public/json/jellystat.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "name": "Jellystat",
- "slug": "jellystat",
- "categories": [
- 9
- ],
- "date_created": "2025-12-08",
- "type": "addon",
- "updateable": true,
- "privileged": false,
- "interface_port": 3000,
- "documentation": "https://github.com/CyferShepard/Jellystat",
- "website": "https://github.com/CyferShepard/Jellystat",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/jellystat.webp",
- "config_path": "/opt/jellystat/.env",
- "description": "A free and open source statistics app for Jellyfin",
- "install_methods": [
- {
- "type": "default",
- "script": "tools/addon/jellystat.sh",
- "resources": {
- "cpu": null,
- "ram": null,
- "hdd": null,
- "os": null,
- "version": null
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": [
- {
- "text": "Requires Node.js 20+ and PostgreSQL (auto-installed if missing)",
- "type": "info"
- },
- {
- "text": "Default PostgreSQL credentials: jellystat / jellystat",
- "type": "info"
- },
- {
- "text": "Update with: update_jellystat",
- "type": "info"
- }
- ]
-}
diff --git a/frontend/public/json/kitchenowl.json b/frontend/public/json/kitchenowl.json
new file mode 100644
index 000000000..e6c150616
--- /dev/null
+++ b/frontend/public/json/kitchenowl.json
@@ -0,0 +1,35 @@
+{
+ "name": "KitchenOwl",
+ "slug": "kitchenowl",
+ "categories": [
+ 13
+ ],
+ "date_created": "2025-12-28",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 80,
+ "documentation": "https://docs.kitchenowl.org/",
+ "website": "https://kitchenowl.org/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/kitchenowl.webp",
+ "config_path": "/opt/kitchenowl/kitchenowl.env",
+ "description": "KitchenOwl is a smart self-hosted grocery list and recipe manager with real-time synchronization, recipe management, meal planning, and expense tracking.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/kitchenowl.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 2048,
+ "hdd": 6,
+ "os": "Debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/loki.json b/frontend/public/json/loki.json
new file mode 100644
index 000000000..fa3362a86
--- /dev/null
+++ b/frontend/public/json/loki.json
@@ -0,0 +1,44 @@
+{
+ "name": "Loki",
+ "slug": "loki",
+ "categories": [9],
+ "date_created": "2025-12-10",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 3100,
+ "documentation": "https://grafana.com/docs/loki/latest/",
+ "website": "https://github.com/grafana/loki",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@master/webp/loki.webp",
+ "config_path": "Debian: /etc/loki/config.yml | Alpine: /etc/loki/loki-local-config.yaml",
+ "description": "Grafana Loki is a set of open source components that can be composed into a fully featured logging stack. A small index and highly compressed chunks simplifies the operation and significantly lowers the cost of Loki.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/loki.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 512,
+ "hdd": 2,
+ "os": "debian",
+ "version": "13"
+ }
+ },
+ {
+ "type": "alpine",
+ "script": "ct/alpine-loki.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 256,
+ "hdd": 1,
+ "os": "alpine",
+ "version": "3.22"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/mail-archiver.json b/frontend/public/json/mail-archiver.json
deleted file mode 100644
index 006cae8ca..000000000
--- a/frontend/public/json/mail-archiver.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "name": "Mail-Archiver",
- "slug": "mail-archiver",
- "categories": [
- 7
- ],
- "date_created": "2025-12-12",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 5000,
- "documentation": "https://github.com/s1t5/mail-archiver/blob/main/doc/Index.md",
- "config_path": "/opt/mail-archiver/.env, /opt/mail-archiver/appsettings.json",
- "website": "https://github.com/s1t5/mail-archiver",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/mail-archiver.webp",
- "description": "Mail-Archiver is a web application for archiving, searching, and exporting emails from multiple accounts. Featuring folder sync, attachment support, mailbox migration and a dashboard.",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/mail-archiver.sh",
- "resources": {
- "cpu": 1,
- "ram": 2048,
- "hdd": 8,
- "os": "Debian",
- "version": "13"
- }
- }
- ],
- "default_credentials": {
- "username": "admin",
- "password": "secure123!"
- },
- "notes": []
-}
diff --git a/frontend/public/json/manyfold.json b/frontend/public/json/manyfold.json
new file mode 100644
index 000000000..26bfa13d9
--- /dev/null
+++ b/frontend/public/json/manyfold.json
@@ -0,0 +1,40 @@
+{
+ "name": "Manyfold",
+ "slug": "manyfold",
+ "categories": [
+ 24
+ ],
+ "date_created": "2025-03-18",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 80,
+ "documentation": "https://manyfold.app/sysadmin/",
+ "website": "https://manyfold.app/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/manyfold.webp",
+ "config_path": "/opt/manyfold/.env",
+ "description": "Manyfold is an open source, self-hosted web application for managing a collection of 3d models, particularly focused on 3d printing.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/manyfold.sh",
+ "resources": {
+ "cpu": 4,
+ "ram": 4096,
+ "hdd": 15,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "Setup library on first connection in /opt/manyfold/data",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/netbird.json b/frontend/public/json/netbird.json
new file mode 100644
index 000000000..2fc4b72eb
--- /dev/null
+++ b/frontend/public/json/netbird.json
@@ -0,0 +1,50 @@
+{
+ "name": "NetBird",
+ "slug": "netbird",
+ "categories": [4],
+ "date_created": "2025-12-02",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": null,
+ "documentation": "https://docs.netbird.io/",
+ "website": "https://netbird.io/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/netbird.webp",
+ "config_path": "/etc/netbird/config.json",
+ "description": "NetBird is an open source VPN management platform that creates secure peer-to-peer networks using WireGuard. It enables secure connectivity between devices anywhere in the world without complex firewall configurations or port forwarding. NetBird offers features like zero-configuration networking, SSO integration, access control policies, and a centralized management dashboard. It's designed to be simple to deploy and manage, making it ideal for connecting remote teams, securing IoT devices, or building secure infrastructure networks.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/netbird.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 512,
+ "hdd": 4,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "The NetBird client (agent) allows a peer to join a pre-existing NetBird deployment. If a NetBird deployment is not yet available, there are both managed and self-hosted options available.",
+ "type": "info"
+ },
+ {
+ "text": "After installation, enter the container and run `netbird` to view the commands.",
+ "type": "info"
+ },
+ {
+ "text": "Use a Setup Key from your NetBird dashboard or SSO login to authenticate during setup or in the container.",
+ "type": "info"
+ },
+ {
+ "text": "Check connection status with `netbird status`.",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/nextexplorer.json b/frontend/public/json/nextexplorer.json
index caa88b336..4e753b3cd 100644
--- a/frontend/public/json/nextexplorer.json
+++ b/frontend/public/json/nextexplorer.json
@@ -1,37 +1,41 @@
{
- "name": "nextExplorer",
- "slug": "nextexplorer",
- "categories": [
- 11,
- 12
- ],
- "date_created": "2025-12-11",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 3000,
- "documentation": "https://explorer.nxz.ai",
- "website": "https://github.com/vikramsoni2/nextExplorer",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nextexplorer.webp",
- "config_path": "/etc/nextExplorer/.env",
- "description": "",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/nextexplorer.sh",
- "resources": {
- "cpu": 2,
- "ram": 3072,
- "hdd": 8,
- "os": "Debian",
- "version": "13"
- }
- }
- ],
- "notes": [
- {
- "text": "Bind mount your volume(s) in the `/mnt` directory",
- "type": "info"
- }
- ]
+ "name": "nextExplorer",
+ "slug": "nextexplorer",
+ "categories": [
+ 11,
+ 12
+ ],
+ "date_created": "2025-12-11",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 3000,
+ "documentation": "https://explorer.nxz.ai",
+ "website": "https://github.com/vikramsoni2/nextExplorer",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nextexplorer.webp",
+ "config_path": "/etc/nextExplorer/.env",
+ "description": "Self-hosted file access for teams, homelabs, and agencies with a refined interface.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/nextexplorer.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 3072,
+ "hdd": 8,
+ "os": "Debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "Bind mount your volume(s) in the `/mnt` directory",
+ "type": "info"
+ }
+ ]
}
diff --git a/frontend/public/json/nodecast-tv.json b/frontend/public/json/nodecast-tv.json
new file mode 100644
index 000000000..8d3f0e1fb
--- /dev/null
+++ b/frontend/public/json/nodecast-tv.json
@@ -0,0 +1,35 @@
+{
+ "name": "nodecast-tv",
+ "slug": "nodecast-tv",
+ "categories": [
+ 13
+ ],
+ "date_created": "2026-01-14",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 3000,
+ "documentation": "https://github.com/technomancer702/nodecast-tv/blob/main/README.md",
+ "website": "https://github.com/technomancer702/nodecast-tv",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/nodecast-tv.webp",
+ "config_path": "",
+ "description": "nodecast-tv is a modern, web-based IPTV player featuring Live TV, EPG, Movies (VOD), and Series support. Built with performance and user experience in mind.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/nodecast-tv.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 4,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/opencloud.json b/frontend/public/json/opencloud.json
index 4dd93e9c9..29fe38a5c 100644
--- a/frontend/public/json/opencloud.json
+++ b/frontend/public/json/opencloud.json
@@ -2,7 +2,7 @@
"name": "OpenCloud",
"slug": "opencloud",
"categories": [
- 2
+ 11
],
"date_created": "2025-12-12",
"type": "ct",
diff --git a/frontend/public/json/openeuler.json b/frontend/public/json/openeuler.json
index da7b2383e..4e0dd7cef 100644
--- a/frontend/public/json/openeuler.json
+++ b/frontend/public/json/openeuler.json
@@ -2,7 +2,7 @@
"name": "openEuler",
"slug": "openeuler",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/opensuse.json b/frontend/public/json/opensuse.json
index 73bb3610e..8a9e7cee0 100644
--- a/frontend/public/json/opensuse.json
+++ b/frontend/public/json/opensuse.json
@@ -2,7 +2,7 @@
"name": "openSUSE",
"slug": "opensuse",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/papra.json b/frontend/public/json/papra.json
new file mode 100644
index 000000000..f3f613b2a
--- /dev/null
+++ b/frontend/public/json/papra.json
@@ -0,0 +1,56 @@
+{
+ "name": "Papra",
+ "slug": "papra",
+ "categories": [
+ 12
+ ],
+ "date_created": "2025-12-30",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 1221,
+ "documentation": "https://github.com/CorentinTh/papra",
+ "website": "https://github.com/CorentinTh/papra",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/papra.webp",
+ "config_path": "/opt/papra/.env",
+ "description": "Papra is a modern, self-hosted document management system with full-text search, OCR support, and automatic document processing. Built with Node.js and featuring a clean web interface for organizing and managing your documents.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/papra.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 10,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "First visit will prompt you to create an account",
+ "type": "info"
+ },
+ {
+ "text": "Tesseract OCR is pre-installed for all languages",
+ "type": "info"
+ },
+ {
+ "text": "Documents are stored in /opt/papra/app-data/documents",
+ "type": "info"
+ },
+ {
+ "text": "Ingestion folder available at /opt/papra/ingestion for automatic document import",
+ "type": "info"
+ },
+ {
+ "text": "Email functionality runs in dry-run mode by default",
+ "type": "warning"
+ }
+ ]
+}
diff --git a/frontend/public/json/petio.json b/frontend/public/json/petio.json
deleted file mode 100644
index 111ff4921..000000000
--- a/frontend/public/json/petio.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "Petio",
- "slug": "petio",
- "categories": [
- 13
- ],
- "date_created": "2025-01-15",
- "type": "ct",
- "updateable": true,
- "privileged": false,
- "interface_port": 7777,
- "documentation": "https://docs.petio.tv/",
- "website": "https://petio.tv/",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/petio.webp",
- "config_path": "/opt/petio",
- "description": "Petio is a third party companion app available to Plex server owners to allow their users to request, review and discover content. It integrates with your existing services, such as Sonarr and Radarr, for seamless content management.",
- "install_methods": [
- {
- "type": "default",
- "script": "ct/petio.sh",
- "resources": {
- "cpu": 2,
- "ram": 1024,
- "hdd": 4,
- "os": "ubuntu",
- "version": "24.04"
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": [
- {
- "text": "Installation path: /opt/Petio",
- "type": "info"
- }
- ]
-}
diff --git a/frontend/public/json/pihole-exporter.json b/frontend/public/json/pihole-exporter.json
deleted file mode 100644
index c27945d03..000000000
--- a/frontend/public/json/pihole-exporter.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "Pi-Hole Exporter",
- "slug": "pihole-exporter",
- "categories": [
- 9
- ],
- "date_created": "2025-12-08",
- "type": "addon",
- "updateable": true,
- "privileged": false,
- "interface_port": 9617,
- "documentation": "https://github.com/eko/pihole-exporter",
- "website": "https://github.com/eko/pihole-exporter",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/pi-hole.webp",
- "config_path": "/opt/pihole-exporter.env",
- "description": "A Prometheus exporter for PI-Hole's Raspberry PI ad blocker",
- "install_methods": [
- {
- "type": "default",
- "script": "tools/addon/pihole-exporter.sh",
- "resources": {
- "cpu": null,
- "ram": null,
- "hdd": null,
- "os": null,
- "version": null
- }
- },
- {
- "type": "alpine",
- "script": "tools/addon/pihole-exporter.sh",
- "resources": {
- "cpu": null,
- "ram": null,
- "hdd": null,
- "os": null,
- "version": null
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": []
-}
diff --git a/frontend/public/json/piler.json b/frontend/public/json/piler.json
index 1b8cb08c3..79d40adb6 100644
--- a/frontend/public/json/piler.json
+++ b/frontend/public/json/piler.json
@@ -2,22 +2,34 @@
"name": "Piler",
"slug": "piler",
"categories": [
- "Email",
- "Archive"
+ 7
],
"date_created": "2025-12-15",
"type": "ct",
"updateable": true,
"privileged": false,
- "interface_port": "80",
+ "interface_port": 80,
"documentation": "https://www.mailpiler.org/",
+ "config_path": "",
"website": "https://www.mailpiler.org/",
"logo": "https://www.mailpiler.org/piler-logo.png",
"description": "Piler is a feature rich open source email archiving solution with support for legal hold, deduplication, full text search, and many more features.",
"install_methods": [
{
"type": "default",
- "script": "ct/piler.sh"
+ "script": "ct/piler.sh",
+ "resources": {
+ "cpu": 4,
+ "ram": 4096,
+ "hdd": 20,
+ "os": "Debian",
+ "version": "12"
+ }
}
- ]
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
}
diff --git a/frontend/public/json/pixelfed.json b/frontend/public/json/pixelfed.json
index a520ff8e3..e607c1913 100644
--- a/frontend/public/json/pixelfed.json
+++ b/frontend/public/json/pixelfed.json
@@ -2,7 +2,7 @@
"name": "Pixelfed",
"slug": "pixelfed",
"categories": [
- 17
+ 0
],
"date_created": "2024-06-15",
"type": "ct",
diff --git a/frontend/public/json/qbittorrent-exporter.json b/frontend/public/json/qbittorrent-exporter.json
deleted file mode 100644
index dba785b6f..000000000
--- a/frontend/public/json/qbittorrent-exporter.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "qbittorrent Exporter",
- "slug": "qbittorrent-exporter",
- "categories": [
- 9
- ],
- "date_created": "2025-11-21",
- "type": "addon",
- "updateable": true,
- "privileged": false,
- "interface_port": 8090,
- "documentation": "https://github.com/martabal/qbittorrent-exporter",
- "website": "https://github.com/martabal/qbittorrent-exporter",
- "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/qbittorrent.webp",
- "config_path": "/opt/qbittorrent-exporter.env",
- "description": "A fast and lightweight prometheus exporter for qBittorrent ",
- "install_methods": [
- {
- "type": "default",
- "script": "tools/addon/qbittorrent-exporter.sh",
- "resources": {
- "cpu": null,
- "ram": null,
- "hdd": null,
- "os": null,
- "version": null
- }
- },
- {
- "type": "alpine",
- "script": "tools/addon/qbittorrent-exporter.sh",
- "resources": {
- "cpu": null,
- "ram": null,
- "hdd": null,
- "os": null,
- "version": null
- }
- }
- ],
- "default_credentials": {
- "username": null,
- "password": null
- },
- "notes": []
-}
diff --git a/frontend/public/json/qui.json b/frontend/public/json/qui.json
new file mode 100644
index 000000000..1c9c8f722
--- /dev/null
+++ b/frontend/public/json/qui.json
@@ -0,0 +1,35 @@
+{
+ "name": "Qui",
+ "slug": "qui",
+ "categories": [
+ 7
+ ],
+ "date_created": "2026-01-13",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 7476,
+ "documentation": "https://github.com/autobrr/qui",
+ "website": "https://github.com/autobrr/qui",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/qui.webp",
+ "config_path": "/root/.config/qui/config.toml",
+ "description": "Qui is a modern, self-hosted web interface for managing multiple qBittorrent instances with support for 10k+ torrents. It provides a clean and responsive interface for monitoring and controlling your qBittorrent downloads across multiple servers.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/qui.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 1024,
+ "hdd": 10,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/rockylinux.json b/frontend/public/json/rockylinux.json
index 9c709b7bf..b0875e6e3 100644
--- a/frontend/public/json/rockylinux.json
+++ b/frontend/public/json/rockylinux.json
@@ -2,7 +2,7 @@
"name": "Rocky Linux",
"slug": "rockylinux",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/romm.json b/frontend/public/json/romm.json
index 0e858bdb1..02a5b199a 100644
--- a/frontend/public/json/romm.json
+++ b/frontend/public/json/romm.json
@@ -8,10 +8,10 @@
"type": "ct",
"updateable": true,
"privileged": false,
- "interface_port": 8080,
+ "interface_port": 80,
"documentation": "https://docs.romm.app/latest/",
"website": "https://romm.app/",
- "config_path": "/opt",
+ "config_path": "/opt/romm/.env",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/romm.webp",
"description": "RomM (ROM Manager) allows you to scan, enrich, browse and play your game collection with a clean and responsive interface. Support for multiple platforms, various naming schemes, and custom tags.",
"install_methods": [
@@ -22,14 +22,14 @@
"cpu": 2,
"ram": 4096,
"hdd": 20,
- "os": "ubuntu",
- "version": "24.04"
+ "os": "debian",
+ "version": "13"
}
}
],
"default_credentials": {
- "username": "romm",
- "password": "changeme"
+ "username": null,
+ "password": null
},
"notes": []
}
diff --git a/frontend/public/json/rustypaste.json b/frontend/public/json/rustypaste.json
new file mode 100644
index 000000000..e71f72687
--- /dev/null
+++ b/frontend/public/json/rustypaste.json
@@ -0,0 +1,40 @@
+{
+ "name": "RustyPaste",
+ "slug": "rustypaste",
+ "categories": [
+ 12
+ ],
+ "date_created": "2025-12-22",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 8000,
+ "documentation": "https://github.com/orhun/rustypaste",
+ "config_path": "/opt/rustypaste/config.toml",
+ "website": "https://github.com/orhun/rustypaste",
+ "logo": "https://github.com/orhun/rustypaste/raw/master/img/rustypaste_logo.png",
+ "description": "Rustypaste is a minimal file upload/pastebin service.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/rustypaste.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 1024,
+ "hdd": 20,
+ "os": "Debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": [
+ {
+ "text": "When updating the script it will backup the whole project including all the uploaded files, make sure to extract it to a safe location or remove",
+ "type": "info"
+ }
+ ]
+}
diff --git a/frontend/public/json/thingsboard.json b/frontend/public/json/thingsboard.json
new file mode 100644
index 000000000..5f38ad3ad
--- /dev/null
+++ b/frontend/public/json/thingsboard.json
@@ -0,0 +1,48 @@
+{
+ "name": "ThingsBoard",
+ "slug": "thingsboard",
+ "categories": [
+ 7
+ ],
+ "date_created": "2026-01-14",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 8080,
+ "documentation": "https://thingsboard.io/docs/",
+ "website": "https://thingsboard.io/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/thingsboard.webp",
+ "config_path": "/etc/thingsboard/conf/thingsboard.conf",
+ "description": "ThingsBoard is an open-source IoT platform for data collection, processing, visualization, and device management. It enables device connectivity via industry standard IoT protocols - MQTT, CoAP and HTTP and supports both cloud and on-premises deployments.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/thingsboard.sh",
+ "resources": {
+ "cpu": 4,
+ "ram": 4096,
+ "hdd": 10,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": "sysadmin@thingsboard.org",
+ "password": "sysadmin"
+ },
+ "notes": [
+ {
+ "text": "Please allow up to 90 seconds for the Web UI to start",
+ "type": "info"
+ },
+ {
+ "text": "Additional demo accounts: tenant@thingsboard.org / tenant and customer@thingsboard.org / customer",
+ "type": "info"
+ },
+ {
+ "text": "Change passwords for all accounts in the account profile page after first login",
+ "type": "warning"
+ }
+ ]
+}
diff --git a/frontend/public/json/tor-snowflake.json b/frontend/public/json/tor-snowflake.json
new file mode 100644
index 000000000..d100e5885
--- /dev/null
+++ b/frontend/public/json/tor-snowflake.json
@@ -0,0 +1,35 @@
+{
+ "name": "Tor Snowflake",
+ "slug": "tor-snowflake",
+ "categories": [
+ 4
+ ],
+ "date_created": "2025-12-19",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": null,
+ "documentation": "https://community.torproject.org/relay/setup/snowflake/standalone/",
+ "website": "https://snowflake.torproject.org/",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/tor.webp",
+ "config_path": "",
+ "description": "Snowflake is a pluggable transport that proxies traffic through temporary proxies using WebRTC. Snowflake allows users in censored locations to access the open internet by connecting through volunteer-run proxies. Running a Snowflake proxy helps users circumvent internet censorship by forwarding their traffic through your server.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/tor-snowflake.sh",
+ "resources": {
+ "cpu": 1,
+ "ram": 512,
+ "hdd": 4,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/tracearr.json b/frontend/public/json/tracearr.json
new file mode 100644
index 000000000..458ec538b
--- /dev/null
+++ b/frontend/public/json/tracearr.json
@@ -0,0 +1,35 @@
+{
+ "name": "Tracearr",
+ "slug": "tracearr",
+ "categories": [
+ 14
+ ],
+ "date_created": "2025-12-28",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 3000,
+ "documentation": "https://github.com/connorgallopo/Tracearr#readme",
+ "config_path": "",
+ "website": "https://github.com/connorgallopo/Tracearr",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/tracearr.webp",
+ "description": "Tracearr is a streaming access manager for Plex, Jellyfin and Emby servers. It answers the question every server owner eventually asks: \"Who's actually using my server, and are they sharing their login?\"",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/tracearr.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 5,
+ "os": "Debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/ubuntu.json b/frontend/public/json/ubuntu.json
index eabf59d8d..4e62dbf2a 100644
--- a/frontend/public/json/ubuntu.json
+++ b/frontend/public/json/ubuntu.json
@@ -2,7 +2,7 @@
"name": "Ubuntu",
"slug": "ubuntu",
"categories": [
- 0
+ 2
],
"date_created": "2025-12-04",
"type": "ct",
diff --git a/frontend/public/json/wishlist.json b/frontend/public/json/wishlist.json
new file mode 100644
index 000000000..4d7f7f45b
--- /dev/null
+++ b/frontend/public/json/wishlist.json
@@ -0,0 +1,35 @@
+{
+ "name": "Wishlist",
+ "slug": "wishlist",
+ "categories": [
+ 0
+ ],
+ "date_created": "2025-12-29",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 3280,
+ "documentation": "https://github.com/cmintey/wishlist/blob/main/README.md#getting-started",
+ "config_path": "/opt/wishlist/.env",
+ "website": "https://github.com/cmintey/wishlist",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cmintey-wishlist.webp",
+ "description": "Wishlist is a self-hosted wishlist application that you can share with your friends and family. You no longer have to wonder what to get your family for the holidays, simply check their wishlist and claim any available item!",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/wishlist.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 5,
+ "os": "Debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/frontend/public/json/yubal.json b/frontend/public/json/yubal.json
new file mode 100644
index 000000000..42bc7676d
--- /dev/null
+++ b/frontend/public/json/yubal.json
@@ -0,0 +1,35 @@
+{
+ "name": "Yubal",
+ "slug": "yubal",
+ "categories": [
+ 13
+ ],
+ "date_created": "2026-01-05",
+ "type": "ct",
+ "updateable": true,
+ "privileged": false,
+ "interface_port": 8000,
+ "documentation": "https://github.com/guillevc/yubal/blob/master/README.md",
+ "website": "https://github.com/guillevc/yubal",
+ "config_path": "/opt/yubal.env",
+ "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/yubal.webp",
+ "description": "YouTube Music album downloader with Spotify metadata auto-tagging.",
+ "install_methods": [
+ {
+ "type": "default",
+ "script": "ct/yubal.sh",
+ "resources": {
+ "cpu": 2,
+ "ram": 2048,
+ "hdd": 15,
+ "os": "debian",
+ "version": "13"
+ }
+ }
+ ],
+ "default_credentials": {
+ "username": null,
+ "password": null
+ },
+ "notes": []
+}
diff --git a/install/almalinux-install.sh b/install/almalinux-install.sh
index af557ad4b..0ead2dd88 100644
--- a/install/almalinux-install.sh
+++ b/install/almalinux-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://almalinux.org/
diff --git a/install/alpine-install.sh b/install/alpine-install.sh
index 2916be18f..4d8a5971a 100644
--- a/install/alpine-install.sh
+++ b/install/alpine-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/install/alpine-loki-install.sh b/install/alpine-loki-install.sh
new file mode 100644
index 000000000..cc5dbfdee
--- /dev/null
+++ b/install/alpine-loki-install.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: hoholms
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/grafana/loki
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Loki"
+$STD apk add loki
+$STD sed -i '/http_addr/s/127.0.0.1/0.0.0.0/g' /etc/conf.d/loki
+$STD rc-service loki start
+$STD rc-update add loki default
+$STD mkdir /tmp/loki/
+$STD chown -R loki:grafana /tmp/loki/
+$STD mkdir /var/log/loki/
+$STD chown -R loki:grafana /var/log/loki/
+$STD chmod 755 /etc/loki/loki-local-config.yaml
+$STD sed -i '/^querier:/,/enable_multi_variant_queries: false/ s/^/#/' /etc/loki/loki-local-config.yaml
+$STD echo "output_log=\"\${output_log:-/var/log/loki/output.log}\"" >> /etc/init.d/loki
+$STD echo "error_log=\"\${error_log:-/var/log/loki/error.log}\"" >> /etc/init.d/loki
+$STD echo "start_stop_daemon_args=\"\${SSD_OPTS} -1 \${output_log} -2 \${error_log}\"" >> /etc/init.d/loki
+$STD rc-service loki restart
+msg_ok "Installed Loki"
+
+msg_info "Installing Promtail"
+$STD apk add loki-promtail
+$STD sed -i '/http_addr/s/127.0.0.1/0.0.0.0/g' /etc/conf.d/loki
+$STD rc-service loki-promtail start
+$STD rc-update add loki-promtail default
+msg_ok "Installed Promtail"
+
+motd_ssh
+customize
diff --git a/install/alpine-ntfy-install.sh b/install/alpine-ntfy-install.sh
index 04aeddc07..197c46a72 100644
--- a/install/alpine-ntfy-install.sh
+++ b/install/alpine-ntfy-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: cobalt (cobaltgit)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://ntfy.sh/
diff --git a/install/alpine-rustypaste-install.sh b/install/alpine-rustypaste-install.sh
new file mode 100644
index 000000000..ddc9ec9cf
--- /dev/null
+++ b/install/alpine-rustypaste-install.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/orhun/rustypaste
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+fetch_and_deploy_gh_release "rustypaste" "orhun/rustypaste" "prebuild" "latest" "/opt/rustypaste" "*x86_64-unknown-linux-musl.tar.gz"
+
+msg_info "Setting up rustypaste"
+cd /opt/rustypaste
+sed -i 's|^address = ".*"|address = "0.0.0.0:8000"|' config.toml
+msg_ok "Set up rustypaste"
+
+msg_info "Creating Service"
+cat <<'EOF' >/etc/init.d/rustypaste
+#!/sbin/openrc-run
+
+name="rustypaste"
+description="rustypaste Service"
+directory="/opt/rustypaste"
+command="/opt/rustypaste/rustypaste"
+command_args=""
+pidfile="/run/${RC_SVCNAME}.pid"
+command_background="yes"
+start_stop_daemon_args="--user root"
+
+depend() {
+ need net
+}
+EOF
+chmod +x /etc/init.d/rustypaste
+rc-update add rustypaste default
+rc-service rustypaste start
+msg_ok "Created Service"
+
+motd_ssh
+customize
diff --git a/install/alpine-valkey-install.sh b/install/alpine-valkey-install.sh
new file mode 100644
index 000000000..66501b3eb
--- /dev/null
+++ b/install/alpine-valkey-install.sh
@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: pshankinclarke (lazarillo)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://valkey.io/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Valkey"
+$STD apk add valkey valkey-openrc valkey-cli
+$STD sed -i 's/^bind .*/bind 0.0.0.0/' /etc/valkey/valkey.conf
+$STD rc-update add valkey default
+$STD rc-service valkey start
+msg_ok "Installed Valkey"
+
+motd_ssh
+customize
diff --git a/install/ampache-install.sh b/install/ampache-install.sh
new file mode 100644
index 000000000..811548ed5
--- /dev/null
+++ b/install/ampache-install.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (Canbiz)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/ampache/ampache
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ flac \
+ vorbis-tools \
+ lame \
+ ffmpeg \
+ inotify-tools \
+ libavcodec-extra \
+ libmp3lame-dev \
+ libtheora-dev \
+ libvorbis-dev \
+ libvpx-dev
+msg_ok "Installed Dependencies"
+
+PHP_VERSION=8.4 PHP_MODULE=bcmath,bz2,curl,gd,imagick,intl,mbstring,mysql,sqlite3,xml,xmlrpc,zip PHP_APACHE=YES setup_php
+setup_mariadb
+MARIADB_DB_USER=ampache MARIADB_DB_NAME=ampache setup_mariadb_db
+
+fetch_and_deploy_gh_release "ampache" "ampache/ampache" "prebuild" "latest" "/opt/ampache" "ampache-*_all_php8.4.zip"
+
+msg_info "Setup Ampache"
+rm -rf /var/www/html
+ln -s /opt/ampache/public /var/www/html
+mv /opt/ampache/public/rest/.htaccess.dist /opt/ampache/public/rest/.htaccess
+mv /opt/ampache/public/play/.htaccess.dist /opt/ampache/public/play/.htaccess
+cp /opt/ampache/config/ampache.cfg.php.dist /opt/ampache/config/ampache.cfg.php
+chmod 664 /opt/ampache/public/rest/.htaccess /opt/ampache/public/play/.htaccess
+msg_ok "Set up Ampache"
+
+msg_info "Configuring Database Connection"
+sed -i 's|^database_hostname = .*|database_hostname = "localhost"|' /opt/ampache/config/ampache.cfg.php
+sed -i 's|^database_name = .*|database_name = "ampache"|' /opt/ampache/config/ampache.cfg.php
+sed -i 's|^database_username = .*|database_username = "ampache"|' /opt/ampache/config/ampache.cfg.php
+sed -i "s|^database_password = .*|database_password = \"${MARIADB_DB_PASS}\"|" /opt/ampache/config/ampache.cfg.php
+chown -R www-data:www-data /opt/ampache
+msg_ok "Configured Database Connection"
+
+msg_info "Importing Database Schema"
+mariadb -u ampache -p"${MARIADB_DB_PASS}" ampache /opt/postgresus/.env
+cat </opt/databasus/.env
# Environment
ENV_MODE=production
@@ -74,7 +74,7 @@ DATABASE_URL=postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
# Migrations
GOOSE_DRIVER=postgres
GOOSE_DBSTRING=postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}?sslmode=disable
-GOOSE_MIGRATION_DIR=/opt/postgresus/migrations
+GOOSE_MIGRATION_DIR=/opt/databasus/migrations
# Security
JWT_SECRET=${JWT_SECRET}
@@ -85,23 +85,23 @@ ADMIN_EMAIL=admin@localhost
ADMIN_PASSWORD=${ADMIN_PASS}
# Paths
-DATA_DIR=/opt/postgresus_data/data
-BACKUP_DIR=/opt/postgresus_data/backups
-LOG_DIR=/opt/postgresus_data/logs
+DATA_DIR=/opt/databasus_data/data
+BACKUP_DIR=/opt/databasus_data/backups
+LOG_DIR=/opt/databasus_data/logs
# PostgreSQL Tools (for creating backups)
PG_DUMP_PATH=/usr/lib/postgresql/17/bin/pg_dump
PG_RESTORE_PATH=/usr/lib/postgresql/17/bin/pg_restore
PSQL_PATH=/usr/lib/postgresql/17/bin/psql
EOF
-chown postgres:postgres /opt/postgresus/.env
-chmod 600 /opt/postgresus/.env
-msg_ok "Configured Postgresus"
+chown postgres:postgres /opt/databasus/.env
+chmod 600 /opt/databasus/.env
+msg_ok "Configured Databasus"
-msg_info "Creating Postgresus Service"
-cat </etc/systemd/system/postgresus.service
+msg_info "Creating Databasus Service"
+cat </etc/systemd/system/databasus.service
[Unit]
-Description=Postgresus - PostgreSQL Backup Management
+Description=Databasus - PostgreSQL Backup Management
After=network.target postgresql.service
Requires=postgresql.service
@@ -109,10 +109,10 @@ Requires=postgresql.service
Type=simple
User=postgres
Group=postgres
-WorkingDirectory=/opt/postgresus
+WorkingDirectory=/opt/databasus
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
-EnvironmentFile=/opt/postgresus/.env
-ExecStart=/opt/postgresus/postgresus
+EnvironmentFile=/opt/databasus/.env
+ExecStart=/opt/databasus/databasus
Restart=always
RestartSec=5
StandardOutput=journal
@@ -122,11 +122,11 @@ StandardError=journal
WantedBy=multi-user.target
EOF
$STD systemctl daemon-reload
-$STD systemctl enable -q --now postgresus
-msg_ok "Created Postgresus Service"
+$STD systemctl enable -q --now databasus
+msg_ok "Created Databasus Service"
msg_info "Configuring Nginx"
-cat </etc/nginx/sites-available/postgresus
+cat </etc/nginx/sites-available/databasus
server {
listen 80;
server_name _;
@@ -147,7 +147,7 @@ server {
}
}
EOF
-ln -sf /etc/nginx/sites-available/postgresus /etc/nginx/sites-enabled/postgresus
+ln -sf /etc/nginx/sites-available/databasus /etc/nginx/sites-enabled/databasus
rm -f /etc/nginx/sites-enabled/default
$STD nginx -t
$STD systemctl enable -q --now nginx
diff --git a/install/debian-install.sh b/install/debian-install.sh
index 99453e489..45fa3fcf3 100644
--- a/install/debian-install.sh
+++ b/install/debian-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source:
diff --git a/install/deferred/ampache-install.sh b/install/deferred/ampache-install.sh
deleted file mode 100644
index 35dfe1430..000000000
--- a/install/deferred/ampache-install.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2024 tteck
-# Author: MickLesk (Canbiz)
-# License: MIT
-# https://github.com/tteck/Proxmox/raw/main/LICENSE
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies (Patience)"
-apt-get install -y \
- apache2 \
- cron \
- flac \
- vorbis-tools \
- lame \
- ffmpeg \
- lsb-release \
- gosu \
- wget \
- curl \
- git \
- make \
- inotify-tools \
- libavcodec-extra \
- libev-libevent-dev \
- libmp3lame-dev \
- libtheora-dev \
- libvorbis-dev \
- libvpx-dev
-msg_ok "Installed Dependencies"
-
-PHP_VERSION=8.4
-PHP_MODULE=bcmath,bz2,cli,common,curl,fpm,gd,imagick,intl,mbstring,mysql,sqlite3,xml,xmlrpc,zip
-PHP_APACHE=YES
-setup_php
-setup_mariadb
-
-msg_info "Setting up Database"
-DB_NAME=ampache2
-DB_USER=ampache2
-DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
-sudo mysql -u root -e "CREATE DATABASE $DB_NAME;"
-sudo mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$DB_PASS');"
-sudo mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
-echo "" >>~/ampache.creds
-echo -e "Ampache Database User: \e $DB_USER\e" >>~/ampache.creds
-echo -e "Ampache Database Password: \e$DB_PASS\e" >>~/ampache.creds
-echo -e "Ampache Database Name: \e$DB_NAME\e" >>~/ampache.creds
-msg_ok "Set up database"
-
-msg_info "Installing Ampache(Patience)"
-cd /opt
-AMPACHE_VERSION=$(wget -q https://github.com/ampache/ampache/releases/latest -O - | grep "title>Release" | cut -d " " -f 4)
-wget https://github.com/ampache/ampache/releases/download/${AMPACHE_VERSION}/ampache-${AMPACHE_VERSION}_all_php8.4.zip
-unzip -q ampache-${AMPACHE_VERSION}_all_php8.4.zip -d ampache
-rm -rf /var/www/html
-ln -s /opt/ampache/public /var/www/html
-sudo mv /opt/ampache/rest/.htaccess.dist /opt/ampache/rest/.htaccess
-sudo mv /opt/ampache/play/.htaccess.dist /opt/ampache/play/.htaccess
-sudo mv /opt/ampache/channel/.htaccess.dist /opt/ampache/channel/.htaccess
-sudo cp /opt/ampache/config/ampache.cfg.php.dist /opt/ampache/config/ampache.cfg.php
-sudo chmod 664 /opt/ampache/rest/.htaccess /opt/ampache/play/.htaccess
-sudo sed -i 's/upload_max_filesize = .*/upload_max_filesize = 50M/' /etc/php/8.4/apache2/php.ini &&
- sudo sed -i 's/post_max_size = .*/post_max_size = 50M/' /etc/php/8.4/apache2/php.ini &&
- sudo sed -i 's/max_execution_time = .*/max_execution_time = 300/' /etc/php/8.4/apache2/php.ini &&
- sudo sed -i 's/memory_limit = .*/memory_limit = 256M/' /etc/php/8.4/apache2/php.ini &&
- sudo systemctl restart apache2
-msg_ok "Installed Ampache"
-
-motd_ssh
-customize
-
-msg_info "Cleaning up"
-$STD apt-get autoremove
-$STD apt-get autoclean
-msg_ok "Cleaned"
diff --git a/install/deferred/docspell-install.sh b/install/deferred/docspell-install.sh
index 43534d727..794e4c9bb 100644
--- a/install/deferred/docspell-install.sh
+++ b/install/deferred/docspell-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT |
diff --git a/install/deferred/jumpserver-install.sh b/install/deferred/jumpserver-install.sh
index 4ccfb09eb..41a13f022 100644
--- a/install/deferred/jumpserver-install.sh
+++ b/install/deferred/jumpserver-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: NΓcolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/jumpserver/jumpserver
diff --git a/install/deferred/maxun-install.sh b/install/deferred/maxun-install.sh
index 704ff04dd..130b90dd7 100644
--- a/install/deferred/maxun-install.sh
+++ b/install/deferred/maxun-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/getmaxun/maxun
diff --git a/install/deferred/maybe_death/kanba-install.sh b/install/deferred/maybe_death/kanba-install.sh
index 10a306ddc..55027ce4f 100644
--- a/install/deferred/maybe_death/kanba-install.sh
+++ b/install/deferred/maybe_death/kanba-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/Kanba-co/kanba
diff --git a/install/petio-install.sh b/install/deferred/maybe_death/petio-install.sh
similarity index 98%
rename from install/petio-install.sh
rename to install/deferred/maybe_death/petio-install.sh
index ff4337c71..6dc6472fb 100644
--- a/install/petio-install.sh
+++ b/install/deferred/maybe_death/petio-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://petio.tv/
diff --git a/install/deferred/nginxproxymanager-install.sh b/install/deferred/nginxproxymanager-install.sh
index 34db0d6a1..aa5f05d12 100644
--- a/install/deferred/nginxproxymanager-install.sh
+++ b/install/deferred/nginxproxymanager-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nginxproxymanager.com/
diff --git a/install/deferred/nimbus-install.sh b/install/deferred/nimbus-install.sh
index c49430481..53ba6b6cb 100644
--- a/install/deferred/nimbus-install.sh
+++ b/install/deferred/nimbus-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/arunavo4/gitea-mirror
diff --git a/install/deferred/ocis-install.sh b/install/deferred/ocis-install.sh
index 987b0397e..1214dc3a1 100644
--- a/install/deferred/ocis-install.sh
+++ b/install/deferred/ocis-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source:
diff --git a/install/deferred/openwebui-install.sh b/install/deferred/openwebui-install.sh
deleted file mode 100644
index 0e9384d8f..000000000
--- a/install/deferred/openwebui-install.sh
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 tteck
-# Author: tteck
-# Co-Author: havardthom
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://openwebui.com/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt-get install -y \
- ffmpeg
-msg_ok "Installed Dependencies"
-
-msg_info "Setup Python3"
-$STD apt-get install -y --no-install-recommends \
- python3 \
- python3-pip
-msg_ok "Setup Python3"
-
-setup_nodejs
-
-msg_info "Installing Open WebUI (Patience)"
-fetch_and_deploy_gh_release "open-webui/open-webui"
-cd /opt/openwebui/backend
-$STD pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
-$STD pip3 install -r requirements.txt -U
-cd /opt/openwebui
-cat </opt/openwebui/.env
-# Ollama URL for the backend to connect
-# The path '/ollama' will be redirected to the specified backend URL
-OLLAMA_BASE_URL=http://0.0.0.0:11434
-OPENAI_API_BASE_URL=''
-OPENAI_API_KEY=''
-# AUTOMATIC1111_BASE_URL="http://localhost:7860"
-# DO NOT TRACK
-SCARF_NO_ANALYTICS=true
-DO_NOT_TRACK=true
-ANONYMIZED_TELEMETRY=false
-ENV=prod
-ENABLE_OLLAMA_API=false
-EOF
-$STD npm install
-export NODE_OPTIONS="--max-old-space-size=3584"
-sed -i "s/git rev-parse HEAD/openssl rand -hex 20/g" /opt/openwebui/svelte.config.js
-$STD npm run build
-msg_ok "Installed Open WebUI"
-
-read -r -p "${TAB3}Would you like to add Ollama? " prompt
-if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
- msg_info "Installing Ollama"
- curl -fsSLO https://ollama.com/download/ollama-linux-amd64.tgz
- tar -C /usr -xzf ollama-linux-amd64.tgz
- rm -rf ollama-linux-amd64.tgz
- cat </etc/systemd/system/ollama.service
-[Unit]
-Description=Ollama Service
-After=network-online.target
-
-[Service]
-Type=exec
-ExecStart=/usr/bin/ollama serve
-Environment=HOME=$HOME
-Environment=OLLAMA_HOST=0.0.0.0
-Restart=always
-RestartSec=3
-
-[Install]
-WantedBy=multi-user.target
-EOF
- systemctl enable -q --now ollama
- sed -i 's/ENABLE_OLLAMA_API=false/ENABLE_OLLAMA_API=true/g' /opt/openwebui/.env
- msg_ok "Installed Ollama"
-fi
-
-msg_info "Creating Service"
-cat </etc/systemd/system/open-webui.service
-[Unit]
-Description=Open WebUI Service
-After=network.target
-
-[Service]
-Type=exec
-WorkingDirectory=/opt/openwebui
-EnvironmentFile=/opt/openwebui/.env
-ExecStart=/opt/openwebui/backend/start.sh
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now open-webui
-msg_ok "Created Service"
-
-motd_ssh
-customize
-
-msg_info "Cleaning up"
-$STD apt-get -y autoremove
-$STD apt-get -y autoclean
-msg_ok "Cleaned"
diff --git a/install/deferred/polaris-install.sh b/install/deferred/polaris-install.sh
index 4f4e77277..8bc6eccf8 100644
--- a/install/deferred/polaris-install.sh
+++ b/install/deferred/polaris-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/agersant/polaris
diff --git a/install/deferred/timescaledb-install.sh b/install/deferred/timescaledb-install.sh
index edcb20faa..aa66a349a 100644
--- a/install/deferred/timescaledb-install.sh
+++ b/install/deferred/timescaledb-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/install/transmission-openvpn-install.sh b/install/deferred/transmission-openvpn-install.sh
similarity index 98%
rename from install/transmission-openvpn-install.sh
rename to install/deferred/transmission-openvpn-install.sh
index eec848203..72b9b985d 100644
--- a/install/transmission-openvpn-install.sh
+++ b/install/deferred/transmission-openvpn-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: SunFlowerOwl
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/haugene/docker-transmission-openvpn
diff --git a/install/deferred/vikunja-install.sh b/install/deferred/vikunja-install.sh
index f56d073d3..7774bd2c7 100644
--- a/install/deferred/vikunja-install.sh
+++ b/install/deferred/vikunja-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://vikunja.io/
diff --git a/install/devuan-install.sh b/install/devuan-install.sh
index 366f394fd..cbd60de17 100644
--- a/install/devuan-install.sh
+++ b/install/devuan-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.devuan.org/
diff --git a/install/docker-install.sh b/install/docker-install.sh
index 8edde48bc..d693f69bd 100644
--- a/install/docker-install.sh
+++ b/install/docker-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.docker.com/
diff --git a/install/ente-install.sh b/install/ente-install.sh
index 9a4fbdee6..a6028e3cb 100644
--- a/install/ente-install.sh
+++ b/install/ente-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/ente-io/ente
@@ -14,19 +14,22 @@ network_check
update_os
msg_info "Installing Dependencies"
-$STD apt-get install -y \
+$STD apt install -y \
libsodium23 \
libsodium-dev \
pkg-config \
caddy \
- gcc \
- curl \
- jq
+ gcc
msg_ok "Installed Dependencies"
PG_VERSION="17" setup_postgresql
+PG_DB_NAME="ente_db" PG_DB_USER="ente" setup_postgresql_db
setup_go
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
+RUST_CRATES="wasm-pack" setup_rust
+$STD rustup target add wasm32-unknown-unknown
+import_local_ip
+
ENTE_CLI_VERSION=$(curl -s https://api.github.com/repos/ente-io/ente/releases | jq -r '[.[] | select(.tag_name | startswith("cli-v"))][0].tag_name')
fetch_and_deploy_gh_release "ente-server" "ente-io/ente" "tarball" "latest" "/opt/ente"
fetch_and_deploy_gh_release "ente-cli" "ente-io/ente" "prebuild" "$ENTE_CLI_VERSION" "/usr/local/bin" "ente-$ENTE_CLI_VERSION-linux-amd64.tar.gz"
@@ -45,28 +48,15 @@ endpoint:
EOF
msg_ok "Configured Ente CLI"
-msg_info "Setting up PostgreSQL"
-DB_NAME="ente_db"
-DB_USER="ente"
-DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)"
-$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
-$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
-$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';"
-$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';"
-$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';"
+msg_info "Saving Ente Credentials"
{
- echo "Ente Credentials"
- echo "Database Name: $DB_NAME"
- echo "Database User: $DB_USER"
- echo "Database Password: $DB_PASS"
- echo ""
echo "Important Configuration Notes:"
- echo "- Frontend is built with IP: $(hostname -I | awk '{print $1}')"
+ echo "- Frontend is built with IP: $LOCAL_IP"
echo "- If IP changes, run: /opt/ente/rebuild-frontend.sh"
- echo "- Museum API: http://$(hostname -I | awk '{print $1}'):8080"
- echo "- Photos UI: http://$(hostname -I | awk '{print $1}'):3000"
- echo "- Accounts UI: http://$(hostname -I | awk '{print $1}'):3001"
- echo "- Auth UI: http://$(hostname -I | awk '{print $1}'):3003"
+ echo "- Museum API: http://$LOCAL_IP:8080"
+ echo "- Photos UI: http://$LOCAL_IP:3000"
+ echo "- Accounts UI: http://$LOCAL_IP:3001"
+ echo "- Auth UI: http://$LOCAL_IP:3003"
echo ""
echo "Post-Installation Steps Required:"
echo "1. Create your first user account via the web UI"
@@ -78,7 +68,7 @@ $STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';"
echo ""
echo "Note: Email verification requires manual intervention since SMTP is not configured"
} >>~/ente.creds
-msg_ok "Set up PostgreSQL"
+msg_ok "Saved Ente Credentials"
msg_info "Building Museum (server)"
cd /opt/ente/server
@@ -105,14 +95,13 @@ SECRET_JWT=$(go run tools/gen-random-keys/main.go 2>/dev/null | grep "jwt" | awk
msg_ok "Generated Secrets"
msg_info "Creating museum.yaml"
-CONTAINER_IP=$(hostname -I | awk '{print $1}')
cat </opt/ente/server/museum.yaml
db:
host: 127.0.0.1
port: 5432
- name: $DB_NAME
- user: $DB_USER
- password: $DB_PASS
+ name: $PG_DB_NAME
+ user: $PG_DB_USER
+ password: $PG_DB_PASS
s3:
are_local_buckets: true
@@ -125,9 +114,9 @@ s3:
bucket: ente-dev
apps:
- public-albums: http://${CONTAINER_IP}:3002
- cast: http://${CONTAINER_IP}:3004
- accounts: http://${CONTAINER_IP}:3001
+ public-albums: http://${LOCAL_IP}:3002
+ cast: http://${LOCAL_IP}:3004
+ accounts: http://${LOCAL_IP}:3001
key:
encryption: $SECRET_ENC
@@ -149,26 +138,24 @@ msg_ok "Created museum.yaml"
read -r -p "Enter the public URL for Ente backend (e.g., https://api.ente.yourdomain.com or http://192.168.1.100:8080) leave empty to use container IP: " backend_url
if [[ -z "$backend_url" ]]; then
- LOCAL_IP=$(hostname -I | awk '{print $1}')
- ENTE_BACKEND_URL="http://$LOCAL_IP:8080"
- msg_info "No URL provided"
- msg_ok "using local IP: $ENTE_BACKEND_URL\n"
+ ENTE_BACKEND_URL="http://$LOCAL_IP:8080"
+ msg_info "No URL provided"
+ msg_ok "using local IP: $ENTE_BACKEND_URL\n"
else
- ENTE_BACKEND_URL="$backend_url"
- msg_info "URL provided"
- msg_ok "Using provided URL: $ENTE_BACKEND_URL\n"
+ ENTE_BACKEND_URL="$backend_url"
+ msg_info "URL provided"
+ msg_ok "Using provided URL: $ENTE_BACKEND_URL\n"
fi
read -r -p "Enter the public URL for Ente albums (e.g., https://albums.ente.yourdomain.com or http://192.168.1.100:3002) leave empty to use container IP: " albums_url
if [[ -z "$albums_url" ]]; then
- LOCAL_IP=$(hostname -I | awk '{print $1}')
- ENTE_ALBUMS_URL="http://$LOCAL_IP:3002"
- msg_info "No URL provided"
- msg_ok "using local IP: $ENTE_ALBUMS_URL\n"
+ ENTE_ALBUMS_URL="http://$LOCAL_IP:3002"
+ msg_info "No URL provided"
+ msg_ok "using local IP: $ENTE_ALBUMS_URL\n"
else
- ENTE_ALBUMS_URL="$albums_url"
- msg_info "URL provided"
- msg_ok "Using provided URL: $ENTE_ALBUMS_URL\n"
+ ENTE_ALBUMS_URL="$albums_url"
+ msg_info "URL provided"
+ msg_ok "Using provided URL: $ENTE_ALBUMS_URL\n"
fi
export NEXT_PUBLIC_ENTE_ENDPOINT=$ENTE_BACKEND_URL
@@ -177,6 +164,7 @@ export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=$ENTE_ALBUMS_URL
msg_info "Building Web Applications"
cd /opt/ente/web
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+source "$HOME/.cargo/env"
$STD yarn install
$STD yarn build
$STD yarn build:accounts
@@ -188,37 +176,38 @@ cp -r apps/accounts/out /var/www/ente/apps/accounts
cp -r apps/auth/out /var/www/ente/apps/auth
cp -r apps/cast/out /var/www/ente/apps/cast
-# Save build configuration for future rebuilds
-cat </opt/ente/rebuild-frontend.sh
+cat <<'EOF' >/opt/ente/rebuild-frontend.sh
#!/usr/bin/env bash
# Rebuild Ente frontend
# Prompt for backend URL
read -r -p "Enter the public URL for Ente backend (e.g., https://api.ente.yourdomain.com or http://192.168.1.100:8080) leave empty to use container IP: " backend_url
-if [[ -z "\$backend_url" ]]; then
+if [[ -z "$backend_url" ]]; then
LOCAL_IP=$(hostname -I | awk '{print $1}')
- ENTE_BACKEND_URL="http://\$LOCAL_IP:8080"
- echo "No URL provided, using local IP: \$ENTE_BACKEND_URL\n"
+ ENTE_BACKEND_URL="http://$LOCAL_IP:8080"
+ echo "No URL provided, using local IP: $ENTE_BACKEND_URL"
else
- ENTE_BACKEND_URL="\$backend_url"
- echo "Using provided URL: \$ENTE_BACKEND_URL\n"
+ ENTE_BACKEND_URL="$backend_url"
+ echo "Using provided URL: $ENTE_BACKEND_URL"
fi
# Prompt for albums URL
read -r -p "Enter the public URL for Ente albums (e.g., https://albums.ente.yourdomain.com or http://192.168.1.100:3002) leave empty to use container IP: " albums_url
-if [[ -z "\$albums_url" ]]; then
- LOCAL_IP=\$(hostname -I | awk '{print $1}')
- ENTE_ALBUMS_URL="http://\$LOCAL_IP:3002"
- echo "No URL provided, using local IP: \$ENTE_ALBUMS_URL\n"
+if [[ -z "$albums_url" ]]; then
+ LOCAL_IP=$(hostname -I | awk '{print $1}')
+ ENTE_ALBUMS_URL="http://$LOCAL_IP:3002"
+ echo "No URL provided, using local IP: $ENTE_ALBUMS_URL"
else
- ENTE_ALBUMS_URL="\$albums_url"
- echo "Using provided URL: \$ENTE_ALBUMS_URL\n"
+ ENTE_ALBUMS_URL="$albums_url"
+ echo "Using provided URL: $ENTE_ALBUMS_URL"
fi
-export NEXT_PUBLIC_ENTE_ENDPOINT=\$ENTE_BACKEND_URL
-export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=\$ENTE_ALBUMS_URL
+export NEXT_PUBLIC_ENTE_ENDPOINT=$ENTE_BACKEND_URL
+export NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=$ENTE_ALBUMS_URL
-echo "Building Web Applications\n"
+echo "Building Web Applications..."
+# Ensure Rust/wasm-pack is available for WASM build
+source "$HOME/.cargo/env"
cd /opt/ente/web
yarn build
yarn build:accounts
@@ -231,7 +220,7 @@ cp -r apps/auth/out /var/www/ente/apps/auth
cp -r apps/cast/out /var/www/ente/apps/cast
systemctl reload caddy
echo "Frontend rebuilt successfully!"
-REBUILD_EOF
+EOF
chmod +x /opt/ente/rebuild-frontend.sh
msg_ok "Built Web Applications"
@@ -253,7 +242,6 @@ systemctl enable -q --now ente-museum
msg_ok "Created Museum Service"
msg_info "Configuring Caddy"
-CONTAINER_IP=$(hostname -I | awk '{print $1}')
cat </etc/caddy/Caddyfile
# Ente Photos - Main Application
:3000 {
@@ -334,18 +322,15 @@ EOF
systemctl reload caddy
msg_ok "Configured Caddy"
-motd_ssh
-customize
-
msg_info "Creating helper scripts"
-cat <<'HELPER_EOF' >/usr/local/bin/ente-get-verification
+cat <<'EOF' >/usr/local/bin/ente-get-verification
#!/usr/bin/env bash
echo "Searching for verification codes in museum logs..."
journalctl -u ente-museum --no-pager | grep -i "verification\|verify\|code" | tail -20
-HELPER_EOF
+EOF
chmod +x /usr/local/bin/ente-get-verification
-cat <<'HELPER_EOF' >/usr/local/bin/ente-upgrade-subscription
+cat <<'EOF' >/usr/local/bin/ente-upgrade-subscription
#!/usr/bin/env bash
if [ -z "$1" ]; then
echo "Usage: ente-upgrade-subscription "
@@ -355,46 +340,11 @@ fi
EMAIL="$1"
echo "Upgrading subscription for: $EMAIL"
ente admin update-subscription -a "$EMAIL" -u "$EMAIL" --no-limit
-HELPER_EOF
+EOF
chmod +x /usr/local/bin/ente-upgrade-subscription
msg_ok "Created helper scripts"
-msg_info "Cleaning up"
-$STD apt -y autoremove
-$STD apt -y autoclean
-msg_ok "Cleaned"
-
-# Final setup summary
-CONTAINER_IP=$(hostname -I | awk '{print $1}')
-echo -e "\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
-echo -e " ${GN}Ente Installation Complete!${CL}"
-echo -e "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
-echo -e "\n${BL}Access URLs:${CL}"
-echo -e " Photos: http://${CONTAINER_IP}:3000"
-echo -e " Accounts: http://${CONTAINER_IP}:3001"
-echo -e " Albums: ${ENTE_ALBUMS_URL}"
-echo -e " Auth: http://${CONTAINER_IP}:3003"
-echo -e " API: ${ENTE_BACKEND_URL}"
-echo -e "\n${YW}β οΈ Important Post-Installation Steps:${CL}"
-echo -e "\n${BL}1. Create your first account:${CL}"
-echo -e " β’ Open http://${CONTAINER_IP}:3000 in your browser"
-echo -e " β’ Click 'Sign Up' and create an account"
-echo -e "\n${BL}2. Verify your email (required):${CL}"
-echo -e " β’ Run: ${GN}ente-get-verification${CL}"
-echo -e " β’ Look for the verification code in the output"
-echo -e " β’ Enter the code in the web UI to complete registration"
-echo -e "\n${BL}3. Remove storage limit:${CL}"
-echo -e " β’ After email verification is complete"
-echo -e " β’ Run: ${GN}ente-upgrade-subscription your@email.com${CL}"
-echo -e " β’ This removes the 10GB limit"
-echo -e "\n${BL}4. If IP changes:${CL}"
-echo -e " β’ Run: ${GN}/opt/ente/rebuild-frontend.sh${CL}"
-echo -e " β’ This rebuilds the frontend with the new IP"
-echo -e "\n${YW}Known Limitations:${CL}"
-echo -e " β’ Email verification requires checking logs (no SMTP configured)"
-echo -e " β’ Account creation must be done manually via web UI"
-echo -e " β’ Subscription upgrade requires CLI after account creation"
-echo -e " β’ Frontend must be rebuilt if container IP changes"
-echo -e "\n${BL}Credentials saved to:${CL} ~/ente.creds"
-echo -e "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n"
+motd_ssh
+customize
+#cleanup_lxc
diff --git a/install/fedora-install.sh b/install/fedora-install.sh
index d59592745..e9f1609b0 100644
--- a/install/fedora-install.sh
+++ b/install/fedora-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://fedoraproject.org/
diff --git a/install/forgejo-runner-install.sh b/install/forgejo-runner-install.sh
new file mode 100644
index 000000000..367b2b76e
--- /dev/null
+++ b/install/forgejo-runner-install.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Simon Friedrich
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://forgejo.org/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+if [[ -z "$var_forgejo_instance" ]]; then
+ read -rp "Forgejo Instance URL (e.g. https://code.forgejo.org): " var_forgejo_instance
+fi
+
+if [[ -z "$var_forgejo_runner_token" ]]; then
+ read -rp "Forgejo Runner Registration Token: " var_forgejo_runner_token
+ echo
+fi
+
+if [[ -z "$var_forgejo_instance" || -z "$var_forgejo_runner_token" ]]; then
+ echo "β Forgejo instance URL and runner token are required."
+ exit 1
+fi
+
+export FORGEJO_INSTANCE="$var_forgejo_instance"
+export FORGEJO_RUNNER_TOKEN="$var_forgejo_runner_token"
+
+msg_info "Installing dependencies"
+$STD apt install -y \
+ git \
+ podman podman-docker
+msg_ok "Installed dependencies"
+
+msg_info "Enabling Podman socket"
+systemctl enable --now podman.socket
+msg_ok "Enabled Podman socket"
+
+msg_info "Installing Forgejo Runner"
+RUNNER_VERSION=$(curl -fsSL https://data.forgejo.org/api/v1/repos/forgejo/runner/releases/latest | jq -r .name | sed 's/^v//')
+curl -fsSL "https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-amd64" -o /usr/local/bin/forgejo-runner
+chmod +x /usr/local/bin/forgejo-runner
+msg_ok "Installed Forgejo Runner"
+
+msg_info "Registering Forgejo Runner"
+export DOCKER_HOST="unix:///run/podman/podman.sock"
+forgejo-runner register \
+ --instance "$FORGEJO_INSTANCE" \
+ --token "$FORGEJO_RUNNER_TOKEN" \
+ --name "$HOSTNAME" \
+ --labels "linux-amd64:docker://node:20-bookworm" \
+ --no-interactive
+msg_ok "Registered Forgejo Runner"
+
+msg_info "Creating Services"
+cat </etc/systemd/system/forgejo-runner.service
+[Unit]
+Description=Forgejo Runner
+Documentation=https://forgejo.org/docs/latest/admin/actions/
+After=podman.socket
+Requires=podman.socket
+
+[Service]
+User=root
+WorkingDirectory=/root
+Environment=DOCKER_HOST=unix:///run/podman/podman.sock
+ExecStart=/usr/local/bin/forgejo-runner daemon
+Restart=on-failure
+RestartSec=10
+TimeoutSec=0
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now forgejo-runner
+msg_ok "Created Services"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/freepbx-install.sh b/install/freepbx-install.sh
index 4a4bd2715..53f9145de 100644
--- a/install/freepbx-install.sh
+++ b/install/freepbx-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Arian Nasr (arian-nasr)
# Updated by: Javier Pastor (vsc55)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/install/frigate-install.sh b/install/frigate-install.sh
index 4d09ec7ac..26822920c 100644
--- a/install/frigate-install.sh
+++ b/install/frigate-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ)
# Co-Authors: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/install/garmin-grafana-install.sh b/install/garmin-grafana-install.sh
index 70070f8c1..46853fae5 100644
--- a/install/garmin-grafana-install.sh
+++ b/install/garmin-grafana-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: aliaksei135
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/arpanghosh8453/garmin-grafana
diff --git a/install/gentoo-install.sh b/install/gentoo-install.sh
index 025226dfd..afa4ccbc7 100644
--- a/install/gentoo-install.sh
+++ b/install/gentoo-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.gentoo.org/
diff --git a/install/gwn-manager-install.sh b/install/gwn-manager-install.sh
new file mode 100644
index 000000000..72b5b7603
--- /dev/null
+++ b/install/gwn-manager-install.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: SlaviΕ‘a AreΕΎina (tremor021)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://www.grandstream.com/products/networking-solutions/wi-fi-management/product/gwn-manager
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ xfonts-utils \
+ fontconfig
+msg_ok "Installed Dependencies"
+
+msg_info "Setting up GWN Manager (Patience)"
+RELEASE=$(curl -s https://www.grandstream.com/support/tools#gwntools \
+ | grep -oP 'https://firmware\.grandstream\.com/GWN_Manager-[^"]+-Ubuntu\.tar\.gz')
+download_file "$RELEASE" "/tmp/gwnmanager.tar.gz"
+cd /tmp
+tar -xzf gwnmanager.tar.gz --strip-components=1
+$STD ./install
+msg_ok "Setup GWN Manager"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/gwnmanager.service
+[Unit]
+Description=GWN Manager
+After=network.target
+Requires=network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/gwn
+ExecStart=/gwn/gwn start
+Restart=on-failure
+RestartSec=10
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q gwnmanager
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/heimdall-dashboard-install.sh b/install/heimdall-dashboard-install.sh
index 9346ea4fd..fc1ea92cb 100644
--- a/install/heimdall-dashboard-install.sh
+++ b/install/heimdall-dashboard-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://heimdall.site/
diff --git a/install/homarr-install.sh b/install/homarr-install.sh
index 85051c2f1..1ead7a69e 100644
--- a/install/homarr-install.sh
+++ b/install/homarr-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/homarr-labs/homarr
diff --git a/install/hoodik-install.sh b/install/hoodik-install.sh
index 31376dab3..4e81df1b4 100644
--- a/install/hoodik-install.sh
+++ b/install/hoodik-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/hudikhq/hoodik
@@ -13,46 +13,47 @@ setting_up_container
network_check
update_os
-msg_info "Installing Dependencies"
-$STD apt-get install -y \
- pkg-config \
- libssl-dev \
- libc6-dev \
- libpq-dev \
- clang \
- llvm \
- nettle-dev \
- build-essential \
- make
-msg_ok "Installed Dependencies"
+#msg_info "Installing Dependencies"
+#$STD apt-get install -y \
+# pkg-config \
+# libssl-dev \
+# libc6-dev \
+# libpq-dev \
+# clang \
+# llvm \
+# nettle-dev \
+# build-essential \
+# make
+#msg_ok "Installed Dependencies"
-setup_rust
-NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
-fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "tarball" "latest" "/opt/hoodik"
+#setup_rust
+#NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
+#fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "tarball" "latest" "/opt/hoodik"
+fetch_and_deploy_gh_release "hoodik" "hudikhq/hoodik" "prebuild" "latest" "/opt/hoodik" "*x86_64.tar.gz"
-msg_info "Installing wasm-pack"
-$STD cargo install wasm-pack
-msg_ok "Installed wasm-pack"
+#msg_info "Installing wasm-pack"
+#$STD cargo install wasm-pack
+#msg_ok "Installed wasm-pack"
-msg_info "Building Hoodik Frontend"
-cd /opt/hoodik
-$STD yarn install --frozen-lockfile
-$STD yarn wasm-pack
-$STD yarn web:build
-msg_ok "Built Hoodik Frontend"
+#msg_info "Building Hoodik Frontend"
+#cd /opt/hoodik
+#$STD yarn install --frozen-lockfile
+#$STD yarn wasm-pack
+#$STD yarn web:build
+#msg_ok "Built Hoodik Frontend"
-msg_info "Building Hoodik Backend"
-cd /opt/hoodik
-$STD cargo build --release
-cp /opt/hoodik/target/release/hoodik /usr/local/bin/hoodik
-chmod +x /usr/local/bin/hoodik
-msg_ok "Built Hoodik Backend"
+#msg_info "Building Hoodik Backend"
+#cd /opt/hoodik
+#$STD cargo build --release
+#cp /opt/hoodik/target/release/hoodik /usr/local/bin/hoodik
+#chmod +x /usr/local/bin/hoodik
+#msg_ok "Built Hoodik Backend"
-msg_info "Cleaning up build artifacts"
-rm -rf /opt/hoodik/target
-rm -rf /root/.cargo/registry
-rm -rf /opt/hoodik/node_modules
-msg_ok "Cleaned up build artifacts"
+#msg_info "Cleaning up build artifacts"
+#rm -rf /opt/hoodik/target
+#rm -rf /root/.cargo/registry
+#rm -rf /opt/hoodik/node_modules
+#msg_ok "Cleaned up build artifacts"
msg_info "Configuring Hoodik"
mkdir -p /opt/hoodik_data
@@ -80,7 +81,8 @@ Type=simple
User=root
WorkingDirectory=/opt/hoodik_data
EnvironmentFile=/opt/hoodik/.env
-ExecStart=/usr/local/bin/hoodik
+#ExecStart=/usr/local/bin/hoodik
+ExecStart=/opt/hoodik
Restart=always
RestartSec=5
diff --git a/install/joplin-server-install.sh b/install/joplin-server-install.sh
new file mode 100644
index 000000000..4a45ea189
--- /dev/null
+++ b/install/joplin-server-install.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: SlaviΕ‘a AreΕΎina (tremor021)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://joplinapp.org/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ git \
+ rsync
+msg_ok "Installed Dependencies"
+
+PG_VERSION="17" setup_postgresql
+PG_DB_NAME="joplin" PG_DB_USER="joplin" setup_postgresql_db
+NODE_VERSION=24 NODE_MODULE="yarn,npm,pm2" setup_nodejs
+mkdir -p /opt/pm2
+export PM2_HOME=/opt/pm2
+$STD pm2 install pm2-logrotate
+$STD pm2 set pm2-logrotate:max_size 100MB
+$STD pm2 set pm2-logrotate:retain 5
+$STD pm2 set pm2-logrotate:compress tr
+fetch_and_deploy_gh_release "joplin-server" "laurent22/joplin" "tarball"
+import_local_ip
+
+msg_info "Setting up Joplin Server (Patience)"
+cd /opt/joplin-server/packages/server
+sed -i "/onenote-converter/d" /opt/joplin-server/packages/lib/package.json
+$STD yarn config set --home enableTelemetry 0
+$STD yarn install
+$STD yarn build
+
+cat </opt/joplin-server/.env
+PM2_HOME=/opt/pm2
+NODE_ENV=production
+APP_BASE_URL=http://$LOCAL_IP:22300
+APP_PORT=22300
+DB_CLIENT=pg
+POSTGRES_PASSWORD=$PG_DB_PASS
+POSTGRES_DATABASE=$PG_DB_NAME
+POSTGRES_PORT=5432
+POSTGRES_HOST=localhost
+EOF
+msg_ok "Setup Joplin Server"
+
+msg_info "Setting up Service"
+cat </etc/systemd/system/joplin-server.service
+[Unit]
+Description=Joplin Server Service
+After=network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/opt/joplin-server/packages/server
+EnvironmentFile=/opt/joplin-server/.env
+ExecStart=/usr/bin/yarn start-prod
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now joplin-server
+msg_ok "Service Setup"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/kitchenowl-install.sh b/install/kitchenowl-install.sh
new file mode 100644
index 000000000..eb90ba9a8
--- /dev/null
+++ b/install/kitchenowl-install.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: snazzybean
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/TomBursch/kitchenowl
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ nginx \
+ build-essential \
+ libpq-dev \
+ libffi-dev \
+ libssl-dev
+msg_ok "Installed Dependencies"
+
+PYTHON_VERSION="3.14" setup_uv
+import_local_ip
+fetch_and_deploy_gh_release "kitchenowl" "TomBursch/kitchenowl" "tarball" "latest" "/opt/kitchenowl"
+rm -rf /opt/kitchenowl/web
+fetch_and_deploy_gh_release "kitchenowl-web" "TomBursch/kitchenowl" "prebuild" "latest" "/opt/kitchenowl/web" "kitchenowl_Web.tar.gz"
+
+msg_info "Setting up KitchenOwl"
+cd /opt/kitchenowl/backend
+#rm -f uv.lock
+$STD uv sync --frozen
+sed -i 's/default=True/default=False/' /opt/kitchenowl/backend/wsgi.py
+mkdir -p /nltk_data
+$STD uv run python -m nltk.downloader -d /nltk_data averaged_perceptron_tagger_eng punkt_tab
+JWT_SECRET=$(openssl rand -hex 32)
+mkdir -p /opt/kitchenowl/data
+cat </opt/kitchenowl/kitchenowl.env
+STORAGE_PATH=/opt/kitchenowl/data
+JWT_SECRET_KEY=${JWT_SECRET}
+NLTK_DATA=/nltk_data
+FRONT_URL=http://${LOCAL_IP}
+FLASK_APP=wsgi.py
+FLASK_ENV=production
+EOF
+set -a
+source /opt/kitchenowl/kitchenowl.env
+set +a
+$STD uv run flask db upgrade
+msg_ok "Set up KitchenOwl"
+
+msg_info "Creating Systemd Service"
+cat </etc/systemd/system/kitchenowl.service
+[Unit]
+Description=KitchenOwl Backend
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/opt/kitchenowl/backend
+EnvironmentFile=/opt/kitchenowl/kitchenowl.env
+ExecStart=/usr/local/bin/uv run wsgi.py
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now kitchenowl
+msg_ok "Created and Started Service"
+
+msg_info "Configuring Nginx"
+rm -f /etc/nginx/sites-enabled/default
+cat <<'EOF' >/etc/nginx/sites-available/kitchenowl.conf
+server {
+ listen 80;
+ server_name _;
+
+ root /opt/kitchenowl/web;
+ index index.html;
+
+ client_max_body_size 100M;
+
+ # Security Headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header X-XSS-Protection "1; mode=block" always;
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+
+ location /api {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_connect_timeout 60s;
+ proxy_send_timeout 60s;
+ proxy_read_timeout 60s;
+ }
+
+ location /socket.io {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_http_version 1.1;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+ # WebSocket Timeouts - allow long-lived connections
+ proxy_read_timeout 86400s;
+ proxy_send_timeout 86400s;
+ }
+}
+EOF
+ln -sf /etc/nginx/sites-available/kitchenowl.conf /etc/nginx/sites-enabled/
+rm -f /etc/nginx/sites-enabled/default
+$STD systemctl reload nginx
+msg_ok "Configured Nginx"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/linkwarden-install.sh b/install/linkwarden-install.sh
new file mode 100644
index 000000000..8f4b569a5
--- /dev/null
+++ b/install/linkwarden-install.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (Canbiz)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://linkwarden.app/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y build-essential
+msg_ok "Installed Dependencies"
+
+NODE_VERSION="22" setup_nodejs
+PG_VERSION="16" setup_postgresql
+PG_DB_NAME="linkwardendb" PG_DB_USER="linkwarden" setup_postgresql_db
+RUST_CRATES="monolith" setup_rust
+fetch_and_deploy_gh_release "linkwarden" "linkwarden/linkwarden"
+import_local_ip
+
+read -r -p "${TAB3}Would you like to add Adminer? " prompt
+if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
+ setup_adminer
+fi
+
+msg_info "Installing Linkwarden (Patience)"
+export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+export PRISMA_HIDE_UPDATE_MESSAGE=1
+export DEBIAN_FRONTEND=noninteractive
+corepack enable
+SECRET_KEY="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32)"
+cd /opt/linkwarden
+$STD yarn workspaces focus linkwarden @linkwarden/web @linkwarden/worker
+# $STD npx playwright install-deps
+# $STD yarn playwright install
+
+cat </opt/linkwarden/.env
+NEXTAUTH_SECRET=${SECRET_KEY}
+NEXTAUTH_URL=http://${LOCAL_IP}:3000
+DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
+EOF
+$STD yarn prisma:generate
+$STD yarn web:build
+$STD yarn prisma:deploy
+rm -rf ~/.cargo/registry ~/.cargo/git ~/.cargo/.package-cache
+rm -rf /root/.cache/yarn
+rm -rf /opt/linkwarden/.next/cache
+msg_ok "Installed Linkwarden"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/linkwarden.service
+[Unit]
+Description=Linkwarden Service
+After=network.target
+
+[Service]
+Type=exec
+Environment=PATH=$PATH
+WorkingDirectory=/opt/linkwarden
+ExecStart=/usr/bin/yarn concurrently:start
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now linkwarden
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/loki-install.sh b/install/loki-install.sh
new file mode 100644
index 000000000..e4aaaa0ea
--- /dev/null
+++ b/install/loki-install.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: bysinka-95
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/grafana/loki
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Setting up Grafana Repository"
+setup_deb822_repo \
+ "grafana" \
+ "https://apt.grafana.com/gpg.key" \
+ "https://apt.grafana.com" \
+ "stable" \
+ "main"
+msg_ok "Grafana Repository setup sucessfully"
+
+msg_info "Installing Loki"
+$STD apt install -y loki
+systemctl enable -q --now loki
+msg_ok "Installed Loki"
+
+msg_info "Installing Promtail"
+$STD apt install -y promtail
+systemctl enable -q --now promtail
+msg_ok "Installed Promtail"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/mail-archiver-install.sh b/install/mail-archiver-install.sh
deleted file mode 100644
index b309966fc..000000000
--- a/install/mail-archiver-install.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: SlaviΕ‘a AreΕΎina (tremor021)
-# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
-# Source: https://github.com/s1t5/mail-archiver
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-setup_deb822_repo \
- "microsoft" \
- "https://packages.microsoft.com/keys/microsoft-2025.asc" \
- "https://packages.microsoft.com/debian/13/prod/" \
- "trixie" \
- "main"
-$STD apt install -y \
- dotnet-sdk-10.0 \
- aspnetcore-runtime-8.0
-msg_ok "Installed Dependencies"
-
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="mailarchiver_db" PG_DB_USER="mailarchiver" setup_postgresql_db
-fetch_and_deploy_gh_release "mail-archiver" "s1t5/mail-archiver" "tarball"
-
-msg_info "Setting up Mail-Archiver"
-mv /opt/mail-archiver /opt/mail-archiver-build
-cd /opt/mail-archiver-build
-$STD dotnet restore
-$STD dotnet publish -c Release -o /opt/mail-archiver
-cp /opt/mail-archiver-build/appsettings.json /opt/mail-archiver/appsettings.json
-sed -i "s|\"DefaultConnection\": \"[^\"]*\"|\"DefaultConnection\": \"Host=localhost;Database=mailarchiver_db;Username=mailarchiver;Password=$PG_DB_PASS\"|" /opt/mail-archiver/appsettings.json
-rm -rf /opt/mail-archiver-build
-
-cat </opt/mail-archiver/.env
-ASPNETCORE_URLS=http://+:5000
-ASPNETCORE_ENVIRONMENT=Production
-TZ=UTC
-EOF
-msg_ok "Setup Mail-Archiver"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/mail-archiver.service
-[Unit]
-Description=Mail-Archiver Service
-After=network.target
-
-[Service]
-EnvironmentFile=/opt/mail-archiver/.env
-WorkingDirectory=/opt/mail-archiver
-ExecStart=/usr/bin/dotnet MailArchiver.dll
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now mail-archiver
-msg_info "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/deferred/manyfold-install.sh b/install/manyfold-install.sh
similarity index 50%
rename from install/deferred/manyfold-install.sh
rename to install/manyfold-install.sh
index f7bb7c2f6..1c82d07d7 100644
--- a/install/deferred/manyfold-install.sh
+++ b/install/manyfold-install.sh
@@ -1,7 +1,8 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: bvdberg01
+# Co-Author: SunFlowerOwl
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
@@ -14,21 +15,24 @@ update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
- lsb-release \
- rbenv \
- libpq-dev \
libarchive-dev \
git \
libmariadb-dev \
redis-server \
nginx \
- libffi-dev \
- libyaml-dev
+ libassimp-dev
msg_ok "Installed Dependencies"
+setup_imagemagick
+
PG_VERSION="16" setup_postgresql
-msg_info "Setting up PostgreSQL"
+fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold/app"
+
+msg_info "Configuring manyfold environment"
+RUBY_INSTALL_VERSION=$(cat /opt/manyfold/app/.ruby-version)
+YARN_VERSION=$(grep '"packageManager":' /opt/manyfold/app/package.json | sed -E 's/.*"(yarn@[0-9\.]+)".*/\1/')
+RELEASE=$(get_latest_github_release "manyfold3d/manyfold")
DB_NAME=manyfold
DB_USER=manyfold
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
@@ -37,32 +41,11 @@ $STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER TEMP
$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 "Manyfold Credentials"
- echo "Manyfold Database User: $DB_USER"
- echo "Manyfold Database Password: $DB_PASS"
- echo "Manyfold Database Name: $DB_NAME"
-} >>~/manyfold.creds
-msg_ok "Set up PostgreSQL"
-
-fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold"
-
-RUBY_INSTALL_VERSION=$(cat /opt/manyfold/.ruby-version)
-YARN_VERSION=$(grep '"packageManager":' /opt/manyfold/package.json | sed -E 's/.*"(yarn@[0-9\.]+)".*/\1/')
-
-NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
-RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" setup_ruby
-
-msg_info "Adding manyfold user"
useradd -m -s /usr/bin/bash manyfold
-msg_ok "Added manyfold user"
-
-msg_info "Setting .env file"
-cat </opt/.env
-export APP_VERSION=12345
+cat </opt/manyfold/.env
+export APP_VERSION=${RELEASE}
export GUID=1002
export PUID=1001
-export PUBLIC_HOSTNAME=subdomain.somehost.org
export PUBLIC_PORT=5000
export REDIS_URL=redis://127.0.0.1:6379/1
export DATABASE_ADAPTER=postgresql
@@ -75,53 +58,68 @@ export MULTIUSER=enabled
export HTTPS_ONLY=false
export RAILS_ENV=production
EOF
-msg_ok ".env file setup"
+cat </opt/manyfold/user_setup.sh
+#!/bin/bash
+
+source /opt/manyfold/.env
+export PATH="/home/manyfold/.rbenv/bin:\$PATH"
+eval "\$(/home/manyfold/.rbenv/bin/rbenv init - bash)"
+cd /opt/manyfold/app
+rbenv global $RUBY_INSTALL_VERSION
+gem install bundler
+bundle install
+gem install sidekiq
+gem install foreman
+corepack enable yarn
+rm -f /opt/manyfold/app/config/credentials.yml.enc
+corepack prepare $YARN_VERSION --activate
+corepack use $YARN_VERSION
+export VISUAL="code --wait"
+bin/rails credentials:edit
+bin/rails db:migrate
+bin/rails assets:precompile
+EOF
+$STD mkdir -p /opt/manyfold/data
+msg_ok "Configured manyfold environment"
+
+NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
+RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" HOME=/home/manyfold setup_ruby
msg_info "Installing Manyfold"
-source /opt/.env
-cd /opt/manyfold
+chown -R manyfold:manyfold /home/manyfold/.rbenv
chown -R manyfold:manyfold /opt/manyfold
-$STD gem install bundler
-$STD rbenv global $RUBY_INSTALL_VERSION
-$STD bundle install
-$STD gem install sidekiq
-$STD npm install --global corepack
-corepack enable yarn
-# $STD corepack prepare $YARN_VERSION --activate
-# $STD corepack use $YARN_VERSION
-chown manyfold:manyfold /opt/.env
-rm /opt/manyfold/config/credentials.yml.enc
-$STD bin/rails credentials:edit
-$STD bin/rails db:migrate
-$STD bin/rails assets:precompile
+chmod +x /opt/manyfold/user_setup.sh
+npm install --global corepack
+$STD sudo -u manyfold bash /opt/manyfold/user_setup.sh
+rm -f /opt/manyfold/user_setup.sh
msg_ok "Installed manyfold"
-msg_info "Creating Service"
-cat </etc/systemd/system/manyfold.service
-[Unit]
-Description=Manyfold3d
-Requires=network.target
-
-[Service]
-Type=simple
-User=root
-Group=root
-WorkingDirectory=/opt/manyfold
-ExecStart=/usr/bin/bash -lc 'source /opt/.env && /opt/manyfold/bin/rails server -b 127.0.0.1 --port 5000 --environment production'
-TimeoutSec=30
-RestartSec=15s
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now manyfold
-
+msg_info "Creating Services"
+source /opt/manyfold/.env
+export PATH="/home/manyfold/.rbenv/shims:/home/manyfold/.rbenv/bin:$PATH"
+$STD foreman export systemd /etc/systemd/system -a manyfold -u manyfold -f /opt/manyfold/app/Procfile
+for f in /etc/systemd/system/manyfold-*.service; do
+ sed -i "s|/bin/bash -lc '|/bin/bash -lc 'source /opt/manyfold/.env \&\& |" "$f"
+done
+systemctl enable -q --now manyfold.target manyfold-rails.1 manyfold-default_worker.1 manyfold-performance_worker.1
cat </etc/nginx/sites-available/manyfold.conf
server {
listen 80;
server_name manyfold;
- root /opt/manyfold/public;
+ root /opt/manyfold/app/public;
+
+ location /cable {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_set_header Host \$host;
+
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade \$http_upgrade;
+ proxy_set_header Connection "Upgrade";
+
+ proxy_set_header X-Real-IP \$remote_addr;
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto \$scheme;
+ }
location / {
try_files \$uri/index.html \$uri @rails;
@@ -139,7 +137,7 @@ EOF
ln -s /etc/nginx/sites-available/manyfold.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
$STD systemctl reload nginx
-msg_ok "Created Service"
+msg_ok "Created Services"
motd_ssh
customize
diff --git a/install/netbird-install.sh b/install/netbird-install.sh
new file mode 100644
index 000000000..c5dace330
--- /dev/null
+++ b/install/netbird-install.sh
@@ -0,0 +1,183 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: TechHutTV
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://netbird.io/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Setting up NetBird Repository"
+setup_deb822_repo \
+ "netbird" \
+ "https://pkgs.netbird.io/debian/public.key" \
+ "https://pkgs.netbird.io/debian" \
+ "stable"
+msg_ok "Set up NetBird Repository"
+
+msg_info "Installing NetBird"
+$STD apt install -y netbird
+msg_ok "Installed NetBird"
+
+msg_info "Enabling NetBird Service"
+$STD systemctl enable -q --now netbird
+msg_ok "Enabled NetBird Service"
+
+echo ""
+echo ""
+echo -e "${BL}NetBird Deployment Type${CL}"
+echo "βββββββββββββββββββββββββββββββββββββββββ"
+echo "Are you using NetBird Managed or Self-Hosted?"
+echo ""
+echo " 1) NetBird Managed (default) - Use NetBird's managed service"
+echo " 2) Self-Hosted - Use your own NetBird management server"
+echo ""
+
+read -r -p "${TAB3}Select deployment type [1]: " DEPLOYMENT_TYPE
+DEPLOYMENT_TYPE="${DEPLOYMENT_TYPE:-1}"
+
+NETBIRD_MGMT_URL=""
+case "$DEPLOYMENT_TYPE" in
+ 1)
+ msg_ok "Using NetBird Managed service"
+ ;;
+ 2)
+ echo ""
+ echo -e "${BL}Self-Hosted Configuration${CL}"
+ echo "βββββββββββββββββββββββββββββββββββββββββ"
+ echo "Enter your NetBird management server URL."
+ echo "Example: https://management.example.com"
+ echo ""
+ read -r -p "Management URL: " NETBIRD_MGMT_URL
+
+ if [[ -z "$NETBIRD_MGMT_URL" ]]; then
+ msg_warn "No management URL provided. Run 'netbird up --management-url ' to connect."
+ else
+ NETBIRD_MGMT_URL="${NETBIRD_MGMT_URL%/}"
+ msg_ok "Management URL configured: ${NETBIRD_MGMT_URL}"
+ fi
+ ;;
+ *)
+ msg_warn "Invalid selection. Using NetBird Managed service."
+ ;;
+esac
+
+echo ""
+echo ""
+echo -e "${BL}NetBird Connection Setup${CL}"
+echo "βββββββββββββββββββββββββββββββββββββββββ"
+echo "Choose how to connect to your NetBird network:"
+echo ""
+if [[ "$DEPLOYMENT_TYPE" == "1" ]]; then
+ echo " 1) Setup Key (default) - Use a pre-generated setup key"
+ echo " 2) SSO Login - Authenticate via browser with your identity provider"
+ echo " 3) Skip - Configure later with 'netbird up'"
+else
+ echo " 1) Setup Key (default) - Use a pre-generated setup key"
+ echo " 2) Skip - Configure later with 'netbird up'"
+fi
+echo ""
+
+read -r -p "Select authentication method [1]: " AUTH_METHOD
+AUTH_METHOD="${AUTH_METHOD:-1}"
+
+if [[ "$DEPLOYMENT_TYPE" == "1" ]]; then
+ case "$AUTH_METHOD" in
+ 1)
+ echo ""
+ echo "Enter your NetBird setup key from the NetBird dashboard."
+ echo ""
+ read -r -p "Setup key: " NETBIRD_SETUP_KEY
+ echo ""
+
+ if [[ -z "$NETBIRD_SETUP_KEY" ]]; then
+ msg_warn "No setup key provided. Run 'netbird up -k ' to connect."
+ else
+ msg_info "Connecting to NetBird with setup key"
+ if $STD netbird up -k "$NETBIRD_SETUP_KEY"; then
+ msg_ok "Connected to NetBird"
+ else
+ msg_warn "Connection failed. Run 'netbird up -k ' to retry."
+ fi
+ fi
+ ;;
+ 2)
+ echo ""
+ echo -e "${BL}SSO Authentication${CL}"
+ echo "βββββββββββββββββββββββββββββββββββββββββ"
+ echo "A login URL will appear below."
+ echo "Copy the URL and open it in your browser to authenticate."
+ echo ""
+
+ msg_info "Starting SSO login"
+ netbird login 2>&1 || true
+ echo ""
+
+ msg_info "Connecting to NetBird"
+ if $STD netbird up; then
+ msg_ok "Connected to NetBird"
+ else
+ msg_warn "Connection failed. Run 'netbird up' to retry."
+ fi
+ ;;
+ 3)
+ msg_ok "Skipped. Run 'netbird up' to connect."
+ ;;
+ *)
+ msg_warn "Invalid selection. Run 'netbird up' to connect."
+ ;;
+ esac
+else
+ case "$AUTH_METHOD" in
+ 1)
+ echo ""
+ echo "Enter your NetBird setup key from the NetBird dashboard."
+ echo ""
+ read -r -p "Setup key: " NETBIRD_SETUP_KEY
+ echo ""
+
+ if [[ -z "$NETBIRD_SETUP_KEY" ]]; then
+ if [[ -z "$NETBIRD_MGMT_URL" ]]; then
+ msg_warn "No setup key provided. Run 'netbird up -k --management-url ' to connect."
+ else
+ msg_warn "No setup key provided. Run 'netbird up -k --management-url $NETBIRD_MGMT_URL' to connect."
+ fi
+ else
+ if [[ -z "$NETBIRD_MGMT_URL" ]]; then
+ msg_error "Management URL is required for self-hosted deployments. Please configure it first."
+ else
+ msg_info "Connecting to NetBird with setup key"
+ if $STD netbird up -k "$NETBIRD_SETUP_KEY" --management-url "$NETBIRD_MGMT_URL"; then
+ msg_ok "Connected to NetBird"
+ else
+ msg_warn "Connection failed. Run 'netbird up -k --management-url $NETBIRD_MGMT_URL' to retry."
+ fi
+ fi
+ fi
+ ;;
+ 2)
+ if [[ -z "$NETBIRD_MGMT_URL" ]]; then
+ msg_ok "Skipped. Run 'netbird up --management-url ' to connect."
+ else
+ msg_ok "Skipped. Run 'netbird up --management-url $NETBIRD_MGMT_URL' to connect."
+ fi
+ ;;
+ *)
+ if [[ -z "$NETBIRD_MGMT_URL" ]]; then
+ msg_warn "Invalid selection. Run 'netbird up --management-url ' to connect."
+ else
+ msg_warn "Invalid selection. Run 'netbird up --management-url $NETBIRD_MGMT_URL' to connect."
+ fi
+ ;;
+ esac
+fi
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/nextexplorer-install.sh b/install/nextexplorer-install.sh
index a1f15a7d7..8ed03263a 100644
--- a/install/nextexplorer-install.sh
+++ b/install/nextexplorer-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/vikramsoni2/nextExplorer
@@ -69,6 +69,8 @@ AUTH_MODE=both
SESSION_SECRET="${SECRET}"
# AUTH_MAX_FAILED=
# AUTH_LOCK_MINUTES=
+# AUTH_USER_EMAIL=
+# AUTH_USER_PASSWORD=
# OIDC_ENABLED=
# OIDC_ISSUER=
@@ -79,6 +81,7 @@ SESSION_SECRET="${SECRET}"
# OIDC_CLIENT_SECRET=
# OIDC_CALLBACK_URL=
# OIDC_SCOPES=
+# OIDC_AUTO_CREATE_USERS=true
# SEARCH_DEEP=
# SEARCH_RIPGREP=
@@ -90,6 +93,12 @@ SESSION_SECRET="${SECRET}"
# ONLYOFFICE_FORCE_SAVE=
# ONLYOFFICE_FILE_EXTENSIONS=
+# COLLABORA_URL=
+# COLLABORA_DISCOVERY_URL=
+# COLLABORA_SECRET=
+# COLLABORA_LANG=
+# COLLABORA_FILE_EXTENSIONS=
+
SHOW_VOLUME_USAGE=true
# USER_DIR_ENABLED=
# SKIP_HOME=
diff --git a/install/nodecast-tv-install.sh b/install/nodecast-tv-install.sh
new file mode 100644
index 000000000..a9d2e3a7b
--- /dev/null
+++ b/install/nodecast-tv-install.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: luismco
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/technomancer702/nodecast-tv
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+fetch_and_deploy_gh_release "nodecast-tv" "technomancer702/nodecast-tv"
+setup_nodejs
+
+msg_info "Installing Modules"
+cd /opt/nodecast-tv
+$STD npm install
+msg_ok "Installed Modules"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/nodecast-tv.service
+[Unit]
+Description=nodecast-tv
+After=network.target
+Wants=network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/opt/nodecast-tv
+ExecStart=/bin/npm run dev
+Restart=on-failure
+RestartSec=10
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now nodecast-tv
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/opencloud-install.sh b/install/opencloud-install.sh
index 92b4e55c8..99ed46366 100644
--- a/install/opencloud-install.sh
+++ b/install/opencloud-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://opencloud.eu
@@ -57,11 +57,11 @@ echo "$COOLPASS" >~/.coolpass
msg_ok "Installed Collabora Online"
# OpenCloud
-fetch_and_deploy_gh_release "opencloud" "opencloud-eu/opencloud" "singlefile" "v4.0.0" "/usr/bin" "opencloud-*-linux-amd64"
+fetch_and_deploy_gh_release "opencloud" "opencloud-eu/opencloud" "singlefile" "v4.1.0" "/usr/bin" "opencloud-*-linux-amd64"
msg_info "Configuring OpenCloud"
DATA_DIR="/var/lib/opencloud/"
-CONFIG_DIR="/etc/opencloud"
+CONFIG_DIR="${CONFIG_DIR}"
ENV_FILE="${CONFIG_DIR}/opencloud.env"
mkdir -p "$DATA_DIR" "$CONFIG_DIR"/assets/apps
@@ -77,6 +77,18 @@ OC_CONFIG_DIR=${CONFIG_DIR}
OC_BASE_DATA_PATH=${DATA_DIR}
STORAGE_SYSTEM_OC_ROOT=${DATA_DIR}/storage/metadata
+## Web
+WEB_ASSET_CORE_PATH=${CONFIG_DIR}/web/assets
+WEB_ASSET_APPS_PATH=${CONFIG_DIR}/web/assets/apps
+WEB_UI_CONFIG_FILE=${CONFIG_DIR}/web/config.json
+# WEB_ASSET_THEMES_PATH=${CONFIG_DIR}/web/assets/themes
+# WEB_UI_THEME_PATH=
+
+## Frontend
+FRONTEND_DISABLE_RADICALE=true
+FRONTEND_GROUPWARE_ENABLED=false
+GRAPH_INCLUDE_OCM_SHAREES=true
+
## Proxy
PROXY_TLS=false
PROXY_CSP_CONFIG_FILE_LOCATION=${CONFIG_DIR}/csp.yaml
@@ -91,9 +103,6 @@ COLLABORATION_HTTP_ADDR=0.0.0.0:9300
COLLABORATION_WOPI_SRC=https://${WOPI_HOST}
COLLABORATION_JWT_SECRET=
-## Applications
-WEB_ASSET_APPS_PATH=${CONFIG_DIR}/assets/apps
-
## Notifications - Email settings
# NOTIFICATIONS_SMTP_HOST=
# NOTIFICATIONS_SMTP_PORT=
diff --git a/install/openeuler-install.sh b/install/openeuler-install.sh
index 2335cbab5..b323b7867 100644
--- a/install/openeuler-install.sh
+++ b/install/openeuler-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.openeuler.org/
diff --git a/install/opensuse-install.sh b/install/opensuse-install.sh
index a144ca238..e41dccbfc 100644
--- a/install/opensuse-install.sh
+++ b/install/opensuse-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.opensuse.org/
diff --git a/install/papra-install.sh b/install/papra-install.sh
new file mode 100644
index 000000000..7a5134881
--- /dev/null
+++ b/install/papra-install.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/papra-hq/papra
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ build-essential \
+ tesseract-ocr \
+ tesseract-ocr-all
+msg_ok "Installed Dependencies"
+
+NODE_VERSION="24" setup_nodejs
+
+RELEASE=$(curl -fsSL https://api.github.com/repos/papra-hq/papra/releases | grep -oP '"tag_name":\s*"\K@papra/docker@[^"]+' | head -n1)
+fetch_and_deploy_gh_release "papra" "papra-hq/papra" "tarball" "${RELEASE}" "/opt/papra"
+
+msg_info "Setup Papra"
+cd /opt/papra
+export COREPACK_ENABLE_NETWORK=1
+$STD corepack enable
+$STD corepack prepare pnpm@10.19.0 --activate
+$STD pnpm install --frozen-lockfile
+$STD pnpm --filter "@papra/app-client..." run build
+$STD pnpm --filter "@papra/app-server..." run build
+msg_ok "Set up Papra"
+
+msg_info "Configuring Papra"
+CONTAINER_IP=$(hostname -I | awk '{print $1}')
+BETTER_AUTH_SECRET=$(openssl rand -hex 32)
+
+mkdir -p /opt/papra/app-data/db
+mkdir -p /opt/papra/app-data/documents
+
+cat >/opt/papra/.env </etc/systemd/system/papra.service </opt/Papra_version.txt
+msg_ok "Created and Started Papra Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/piler-install.sh b/install/piler-install.sh
index 18b9374ac..1eeadff04 100644
--- a/install/piler-install.sh
+++ b/install/piler-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://www.mailpiler.org/
@@ -22,49 +22,41 @@ $STD apt install -y \
poppler-utils \
unrtf \
tnef \
- clamav \
- clamav-daemon \
memcached \
sysstat \
python3 \
- python3-mysqldb
+ python3-mysqldb \
+ ca-certificates \
+ gnupg
msg_ok "Installed Dependencies"
import_local_ip
setup_mariadb
-MARIADB_DB_NAME="piler" MARIADB_DB_USER="piler" setup_mysql_db
-PHP_VERSION="8.4" PHP_FPM="YES" PHP_MODULE="ldap,gd,memcached,pdo,mysql,curl,zip" setup_php
+MARIADB_DB_NAME="piler" MARIADB_DB_USER="piler" setup_mariadb_db
+PHP_VERSION="8.3" PHP_FPM="YES" PHP_MODULE="ldap,gd,memcached,pdo,mysql,curl,zip" setup_php
msg_info "Installing Manticore Search"
-curl -fsSL https://repo.manticoresearch.com/manticore-repo.noarch.deb -o /tmp/manticore-repo.deb
-$STD dpkg -i /tmp/manticore-repo.deb
+cd /tmp
+wget -q https://repo.manticoresearch.com/manticore-repo.noarch.deb
+$STD dpkg -i /tmp/manticore-repo.noarch.deb
$STD apt update
-$STD apt install -y manticore manticore-extra
-rm -f /tmp/manticore-repo.deb
+$STD apt install -y manticore manticore-columnar-lib manticore-extra
+rm -f /tmp/manticore-repo.noarch.deb
+$STD systemctl stop manticore
+$STD systemctl disable manticore
msg_ok "Installed Manticore Search"
msg_info "Installing Piler"
-VERSION="1.4.8"
-cd /tmp
-curl -fsSL "https://github.com/jsuto/piler/releases/download/piler-${VERSION}/piler_${VERSION}-bookworm_amd64.deb" -o piler.deb
-curl -fsSL "https://github.com/jsuto/piler/releases/download/piler-${VERSION}/piler-webui_${VERSION}-bookworm_amd64.deb" -o piler-webui.deb
-
-$STD dpkg -i piler.deb
-$STD apt-get -f install -y
-$STD dpkg -i piler-webui.deb
-$STD apt-get -f install -y
-
-rm -f piler.deb piler-webui.deb
-msg_ok "Installed Piler v${VERSION}"
+fetch_and_deploy_gh_release "piler" "jsuto/piler" "binary" "latest" "/tmp" "piler_*-noble-*_amd64.deb"
+fetch_and_deploy_gh_release "piler-webui" "jsuto/piler" "binary" "latest" "/tmp" "piler-webui_*-noble-*_amd64.deb"
+msg_ok "Installed Piler"
msg_info "Configuring Piler Database"
-cd /usr/local/share/piler
-mysql -u root "${MARIADB_DB_NAME}" /dev/null || true
msg_ok "Configured Piler Database"
msg_info "Configuring Piler"
PILER_KEY=$(openssl rand -hex 16)
-
cat </etc/piler/piler.conf
hostid=piler.${LOCAL_IP}.nip.io
update_counters_to_memcached=1
@@ -88,9 +80,6 @@ iv=0123456789ABCDEF
memcached_servers=127.0.0.1
-enable_clamav=1
-clamd_socket=/var/run/clamav/clamd.ctl
-
spam_header_line=X-Spam-Status: Yes
verbosity=1
@@ -157,8 +146,8 @@ msg_info "Creating Piler Service"
cat </etc/systemd/system/piler.service
[Unit]
Description=Piler Email Archiving
-After=network.target mysql.service manticore.service
-Requires=mysql.service manticore.service
+After=network.target mysql.service manticore.service memcached.service
+Requires=mysql.service
[Service]
Type=forking
@@ -176,23 +165,22 @@ EOF
$STD systemctl daemon-reload
$STD systemctl enable --now manticore
$STD systemctl enable --now memcached
-$STD systemctl enable --now clamav-daemon
$STD systemctl enable --now piler
msg_ok "Created Piler Service"
msg_info "Configuring PHP-FPM Pool"
-cp /etc/php/8.4/fpm/pool.d/www.conf /etc/php/8.4/fpm/pool.d/piler.conf
-sed -i 's/\[www\]/[piler]/' /etc/php/8.4/fpm/pool.d/piler.conf
-sed -i 's/^user = www-data/user = piler/' /etc/php/8.4/fpm/pool.d/piler.conf
-sed -i 's/^group = www-data/group = piler/' /etc/php/8.4/fpm/pool.d/piler.conf
-sed -i 's|^listen = .*|listen = /run/php/php8.4-fpm-piler.sock|' /etc/php/8.4/fpm/pool.d/piler.conf
-$STD systemctl restart php8.4-fpm
+cp /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/piler.conf
+sed -i 's/\[www\]/[piler]/' /etc/php/8.3/fpm/pool.d/piler.conf
+sed -i 's/^user = www-data/user = piler/' /etc/php/8.3/fpm/pool.d/piler.conf
+sed -i 's/^group = www-data/group = piler/' /etc/php/8.3/fpm/pool.d/piler.conf
+sed -i 's|^listen = .*|listen = /run/php/php8.3-fpm-piler.sock|' /etc/php/8.3/fpm/pool.d/piler.conf
+$STD systemctl restart php8.3-fpm
msg_ok "Configured PHP-FPM Pool"
msg_info "Configuring Piler Web GUI"
-cd /var/www/piler
-
-cat </var/www/piler/config-site.php
+# Check if config-site.php already exists (created by .deb package)
+if [ ! -f /var/www/piler/config-site.php ]; then
+ cat </var/www/piler/config-site.php
/var/www/piler/config-site.php
\$config['HEADER_LINE_TO_HIDE'] = 'X-Envelope-To:';
?>
EOF
+fi
chown -R piler:piler /var/www/piler
chmod 755 /var/www/piler
@@ -260,7 +249,7 @@ server {
}
location ~ \.php$ {
- fastcgi_pass unix:/run/php/php8.4-fpm-piler.sock;
+ fastcgi_pass unix:/run/php/php8.3-fpm-piler.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
diff --git a/install/pixelfed-install.sh b/install/pixelfed-install.sh
index a122fe356..f2b9ee78e 100644
--- a/install/pixelfed-install.sh
+++ b/install/pixelfed-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://pixelfed.org/
diff --git a/install/plex-install.sh b/install/plex-install.sh
deleted file mode 100644
index 641bed6e2..000000000
--- a/install/plex-install.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.plex.tv/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Setting Up Hardware Acceleration"
-$STD apt -y install {va-driver-all,ocl-icd-libopencl1,intel-opencl-icd,vainfo,intel-gpu-tools}
-if [[ -d /dev/dri ]]; then
- chgrp video /dev/dri 2>/dev/null || true
- chmod 755 /dev/dri 2>/dev/null || true
- chmod 660 /dev/dri/* 2>/dev/null || true
- $STD adduser "$(id -u -n)" video
- $STD adduser "$(id -u -n)" render
-fi
-msg_ok "Set Up Hardware Acceleration"
-
-msg_info "Setting Up Plex Media Server Repository"
-curl -fsSL https://downloads.plex.tv/plex-keys/PlexSign.key | tee /usr/share/keyrings/PlexSign.asc >/dev/null
-cat </etc/apt/sources.list.d/plexmediaserver.sources
-Types: deb
-URIs: https://downloads.plex.tv/repo/deb/
-Suites: public
-Components: main
-Signed-By: /usr/share/keyrings/PlexSign.asc
-EOF
-msg_ok "Set Up Plex Media Server Repository"
-
-msg_info "Installing Plex Media Server"
-$STD apt update
-$STD apt -o Dpkg::Options::="--force-confold" install -y plexmediaserver
-if [[ "$CTTYPE" == "0" ]]; then
- sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:root,plex/' -e 's/^render:x:108:root$/ssl-cert:x:108:plex/' /etc/group
-else
- sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:plex/' -e 's/^render:x:108:$/ssl-cert:x:108:/' /etc/group
-fi
-msg_ok "Installed Plex Media Server"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/plex2-install.sh b/install/plex2-install.sh
deleted file mode 100644
index 64a61e847..000000000
--- a/install/plex2-install.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 tteck
-# Author: tteck (tteckster)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.plex.tv/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-setup_hwaccel
-
-msg_info "Setting Up Plex Media Server Repository"
-curl -fsSL https://downloads.plex.tv/plex-keys/PlexSign.key | tee /usr/share/keyrings/PlexSign.asc >/dev/null
-cat </etc/apt/sources.list.d/plexmediaserver.sources
-Types: deb
-URIs: https://downloads.plex.tv/repo/deb/
-Suites: public
-Components: main
-Signed-By: /usr/share/keyrings/PlexSign.asc
-EOF
-msg_ok "Set Up Plex Media Server Repository"
-
-msg_info "Installing Plex Media Server"
-$STD apt update
-$STD apt -o Dpkg::Options::="--force-confold" install -y plexmediaserver
-if [[ "$CTTYPE" == "0" ]]; then
- sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:root,plex/' -e 's/^render:x:108:root$/ssl-cert:x:108:plex/' /etc/group
-else
- sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:plex/' -e 's/^render:x:108:$/ssl-cert:x:108:/' /etc/group
-fi
-msg_ok "Installed Plex Media Server"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/qui-install.sh b/install/qui-install.sh
new file mode 100644
index 000000000..8e45ed000
--- /dev/null
+++ b/install/qui-install.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (Canbiz)
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/autobrr/qui
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+fetch_and_deploy_gh_release "qui" "autobrr/qui" "prebuild" "latest" "/usr/local/bin" "qui_*_linux_x86_64.tar.gz"
+chmod +x /usr/local/bin/qui
+ln -sf /usr/local/bin/qui /usr/bin/qui
+ln -sf /usr/local/bin/qui /opt/qui
+
+msg_info "Creating Qui Service"
+cat </etc/systemd/system/qui.service
+[Unit]
+Description=Qui - qBittorrent Web UI
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=simple
+ExecStart=/usr/local/bin/qui serve
+Restart=on-failure
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now qui
+msg_ok "Created Qui Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/rockylinux-install.sh b/install/rockylinux-install.sh
index 4922bd520..247377dc5 100644
--- a/install/rockylinux-install.sh
+++ b/install/rockylinux-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://rockylinux.org/
diff --git a/install/romm-install.sh b/install/romm-install.sh
index 438e4e5a7..1f442c10f 100644
--- a/install/romm-install.sh
+++ b/install/romm-install.sh
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: DevelopmentCats
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Co-author: AlphaLawless
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://romm.app
-# Updated: 03/10/2025
+# Updated: 25/12/2025
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
@@ -16,67 +17,124 @@ update_os
msg_info "Installing dependencies"
$STD apt-get install -y \
- acl \
- build-essential \
- libssl-dev \
- libffi-dev \
- python3-dev \
- python3-pip \
- python3-venv \
- libmariadb3 \
- libmariadb-dev \
- libpq-dev \
- redis-tools \
- p7zip \
- tzdata \
- jq
-msg_ok "Installed core dependencies"
+ acl \
+ build-essential \
+ gcc \
+ g++ \
+ make \
+ libssl-dev \
+ libffi-dev \
+ libmagic-dev \
+ python3-dev \
+ python3-pip \
+ python3-venv \
+ libmariadb3 \
+ libmariadb-dev \
+ libpq-dev \
+ libbz2-dev \
+ libreadline-dev \
+ libsqlite3-dev \
+ zlib1g-dev \
+ liblzma-dev \
+ libncurses5-dev \
+ libncursesw5-dev \
+ redis-server \
+ redis-tools \
+ p7zip-full \
+ tzdata \
+ nginx
+msg_ok "Installed dependencies"
-PYTHON_VERSION="3.12" setup_uv
-NODE_VERSION="22" NODE_MODULE="serve" setup_nodejs
+UV_VERSION="0.7.19" PYTHON_VERSION="3.13" setup_uv
+NODE_VERSION="22" setup_nodejs
setup_mariadb
+MARIADB_DB_NAME="romm" MARIADB_DB_USER="romm" setup_mariadb_db
-msg_info "Configuring Database"
-DB_NAME=romm
-DB_USER=romm
-DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
-$STD mariadb -u root -e "CREATE DATABASE IF NOT EXISTS $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
-$STD mariadb -u root -e "CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
-$STD mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
-{
- echo "RomM-Credentials"
- echo "RomM Database User: $DB_USER"
- echo "RomM Database Password: $DB_PASS"
- echo "RomM Database Name: $DB_NAME"
-} >~/romm.creds
-chmod 600 ~/romm.creds
-msg_ok "Configured Database"
-
-msg_info "Creating romm user and directories"
-id -u romm &>/dev/null || useradd -r -m -d /var/lib/romm -s /bin/bash romm
+msg_info "Creating directories"
mkdir -p /opt/romm \
- /var/lib/romm/config \
- /var/lib/romm/resources \
- /var/lib/romm/assets/{saves,states,screenshots} \
- /var/lib/romm/library/roms/{gba,gbc,ps} \
- /var/lib/romm/library/bios/{gba,ps}
-chown -R romm:romm /opt/romm /var/lib/romm
-msg_ok "Created romm user and directories"
+ /var/lib/romm/config \
+ /var/lib/romm/resources \
+ /var/lib/romm/assets/{saves,states,screenshots} \
+ /var/lib/romm/library/roms \
+ /var/lib/romm/library/bios
+msg_ok "Created directories"
-msg_info "Configuring Database"
-DB_NAME=romm
-DB_USER=romm
-DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
-$STD mariadb -u root -e "CREATE DATABASE $DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
-$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
-$STD mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
-{
- echo "RomM-Credentials"
- echo "RomM Database User: $DB_USER"
- echo "RomM Database Password: $DB_PASS"
- echo "RomM Database Name: $DB_NAME"
-} >~/romm.creds
-msg_ok "Configured Database"
+msg_info "Creating configuration file"
+cat >/var/lib/romm/config/config.yml <<'CONFIGEOF'
+# RomM Configuration File
+# Documentation: https://docs.romm.app/latest/Getting-Started/Configuration-File/
+# Only uncomment the lines you want to use/modify
+
+# exclude:
+# platforms:
+# - excluded_folder_a
+# roms:
+# single_file:
+# extensions:
+# - xml
+# - txt
+# names:
+# - '._*'
+# - '*.nfo'
+# multi_file:
+# names:
+# - downloaded_media
+# - media
+
+# system:
+# platforms:
+# gc: ngc
+# ps1: psx
+
+# The folder name where your roms are located (relative to library path)
+# filesystem:
+# roms_folder: 'roms'
+
+# scan:
+# priority:
+# metadata:
+# - "igdb"
+# - "moby"
+# - "ss"
+# - "ra"
+# artwork:
+# - "igdb"
+# - "moby"
+# - "ss"
+# region:
+# - "us"
+# - "eu"
+# - "jp"
+# language:
+# - "en"
+# media:
+# - box2d
+# - box3d
+# - screenshot
+# - manual
+
+# emulatorjs:
+# debug: false
+# cache_limit: null
+CONFIGEOF
+chmod 644 /var/lib/romm/config/config.yml
+msg_ok "Created configuration file"
+
+fetch_and_deploy_gh_release "RetroAchievements" "RetroAchievements/RALibretro" "prebuild" "latest" "/opt/RALibretro" "RAHasher-x64-Linux-*.zip"
+
+msg_info "Building RAHasher (RetroAchievements)"
+cd /opt/RALibretro
+sed -i '22a #include ' ./src/Util.h
+sed -i '6a #include ' \
+ ./src/libchdr/deps/zlib-1.3.1/gzlib.c \
+ ./src/libchdr/deps/zlib-1.3.1/gzread.c \
+ ./src/libchdr/deps/zlib-1.3.1/gzwrite.c
+$STD make HAVE_CHD=1 -f ./Makefile.RAHasher
+cp ./bin64/RAHasher /usr/bin/RAHasher
+chmod +x /usr/bin/RAHasher
+cd /tmp
+rm -rf /tmp/RALibretro
+msg_ok "Built RAHasher"
fetch_and_deploy_gh_release "romm" "rommapp/romm"
@@ -88,13 +146,14 @@ AUTH_SECRET_KEY=$(openssl rand -hex 32)
cat >/opt/romm/.env </etc/nginx/sites-available/romm <<'EOF'
+upstream romm_backend {
+ server 127.0.0.1:5000;
+}
+
+map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+}
+
+server {
+ listen 80;
+ server_name _;
+ root /opt/romm/frontend/dist;
+ client_max_body_size 0;
+
+ # Frontend SPA
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+
+ # EmulatorJS player - requires COOP/COEP headers for SharedArrayBuffer
+ location ~ ^/rom/.*/ejs$ {
+ add_header Cross-Origin-Embedder-Policy "require-corp";
+ add_header Cross-Origin-Opener-Policy "same-origin";
+ try_files $uri /index.html;
+ }
+
+ # Backend API
+ location /api {
+ proxy_pass http://romm_backend;
+ proxy_buffering off;
+ proxy_request_buffering off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ # WebSocket and Netplay
+ location ~ ^/(ws|netplay) {
+ proxy_pass http://romm_backend;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Host $host;
+ proxy_read_timeout 86400;
+ }
+
+ # OpenAPI docs
+ location = /openapi.json {
+ proxy_pass http://romm_backend;
+ }
+
+ # Internal library file serving
+ location /library/ {
+ internal;
+ alias /var/lib/romm/library/;
+ }
+}
+EOF
+
+rm -f /etc/nginx/sites-enabled/default
+ln -sf /etc/nginx/sites-available/romm /etc/nginx/sites-enabled/romm
+$STD nginx -t
+systemctl restart nginx
+systemctl enable -q nginx
+msg_ok "Configured nginx"
msg_info "Creating services"
-
cat >/etc/systemd/system/romm-backend.service </etc/systemd/system/romm-frontend.service </etc/systemd/system/romm-worker.service </etc/systemd/system/romm-scheduler.service </etc/systemd/system/romm-watcher.service </etc/systemd/system/rustypaste.service
+[Unit]
+Description=rustypaste Service
+After=network.target
+
+[Service]
+WorkingDirectory=/opt/rustypaste
+ExecStart=/opt/rustypaste/rustypaste
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now rustypaste
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/rybbit-install.sh b/install/rybbit-install.sh
index 7bec945aa..8f45864ef 100644
--- a/install/rybbit-install.sh
+++ b/install/rybbit-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
# Source: https://github.com/rybbit-io/rybbit
diff --git a/install/thingsboard-install.sh b/install/thingsboard-install.sh
new file mode 100644
index 000000000..4745b2fe9
--- /dev/null
+++ b/install/thingsboard-install.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/thingsboard/thingsboard
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ libharfbuzz0b \
+ fontconfig \
+ fonts-dejavu-core
+msg_ok "Installed Dependencies"
+
+JAVA_VERSION="17" setup_java
+PG_VERSION="16" setup_postgresql
+PG_DB_NAME="thingsboard_db" PG_DB_USER="thingsboard" setup_postgresql_db
+fetch_and_deploy_gh_release "thingsboard" "thingsboard/thingsboard" "binary" "latest" "/tmp" "thingsboard-*.deb"
+
+msg_info "Configuring ThingsBoard"
+cat >/etc/thingsboard/conf/thingsboard.conf <~/.tor-snowflake
+msg_ok "Built Snowflake Proxy v${RELEASE}"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/snowflake-proxy.service
+[Unit]
+Description=Snowflake Proxy Service
+Documentation=https://snowflake.torproject.org/
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=simple
+User=snowflake
+Group=snowflake
+WorkingDirectory=/opt/tor-snowflake/proxy
+ExecStart=/opt/tor-snowflake/proxy/snowflake-proxy -verbose -unsafe-logging
+Restart=always
+RestartSec=10
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now snowflake-proxy
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/tracearr-install.sh b/install/tracearr-install.sh
new file mode 100644
index 000000000..57c71d715
--- /dev/null
+++ b/install/tracearr-install.sh
@@ -0,0 +1,151 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2025 community-scripts ORG
+# Author: durzo
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/connorgallopo/Tracearr
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y redis-server
+msg_ok "Installed Dependencies"
+
+PNPM_VERSION="$(curl -fsSL "https://raw.githubusercontent.com/connorgallopo/Tracearr/refs/heads/main/package.json" | jq -r '.packageManager | split("@")[1]')"
+NODE_VERSION="22" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
+PG_VERSION="18" setup_postgresql
+
+msg_info "Installing TimescaleDB"
+setup_deb822_repo \
+ "timescaledb" \
+ "https://packagecloud.io/timescale/timescaledb/gpgkey" \
+ "https://packagecloud.io/timescale/timescaledb/debian" \
+ "$(get_os_info codename)" \
+ "main"
+$STD apt install -y \
+ timescaledb-2-postgresql-18 \
+ timescaledb-tools \
+ timescaledb-toolkit-postgresql-18
+total_ram_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
+ram_for_tsdb=$((total_ram_kb / 1024 / 2))
+$STD timescaledb-tune -yes -memory "$ram_for_tsdb"MB
+$STD systemctl restart postgresql
+msg_ok "Installed TimescaleDB"
+
+msg_info "Creating PostgreSQL Database"
+PG_DB_NAME="tracearr" PG_DB_USER="tracearr" PG_DB_EXTENSIONS="timescaledb,timescaledb_toolkit" setup_postgresql_db
+msg_ok "Created PostgreSQL Database"
+
+fetch_and_deploy_gh_release "tracearr" "connorgallopo/Tracearr" "tarball" "latest" "/opt/tracearr.build"
+
+msg_info "Building Tracearr"
+export TZ=$(cat /etc/timezone)
+cd /opt/tracearr.build
+$STD pnpm install --frozen-lockfile --force
+$STD pnpm turbo telemetry disable
+$STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
+mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db}
+cp -rf package.json /opt/tracearr/
+cp -rf pnpm-workspace.yaml /opt/tracearr/
+cp -rf pnpm-lock.yaml /opt/tracearr/
+cp -rf apps/server/package.json /opt/tracearr/apps/server/
+cp -rf apps/server/dist /opt/tracearr/apps/server/dist
+cp -rf apps/web/dist /opt/tracearr/apps/web/dist
+cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
+cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
+cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
+cp -rf data /opt/tracearr/data
+mkdir -p /opt/tracearr/data/image-cache
+rm -rf /opt/tracearr.build
+cd /opt/tracearr
+$STD pnpm install --prod --frozen-lockfile --ignore-scripts
+msg_ok "Built Tracearr"
+
+msg_info "Configuring Tracearr"
+$STD useradd -r -s /bin/false -U tracearr
+$STD chown -R tracearr:tracearr /opt/tracearr
+install -d -m 750 -o tracearr -g tracearr /data/tracearr
+export JWT_SECRET=$(openssl rand -hex 32)
+export COOKIE_SECRET=$(openssl rand -hex 32)
+cat </data/tracearr/.env
+DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
+REDIS_URL=redis://127.0.0.1:6379
+PORT=3000
+HOST=0.0.0.0
+NODE_ENV=production
+TZ=${TZ}
+LOG_LEVEL=info
+JWT_SECRET=$JWT_SECRET
+COOKIE_SECRET=$COOKIE_SECRET
+APP_VERSION=$(cat /root/.tracearr)
+#CORS_ORIGIN=http://localhost:5173
+#MOBILE_BETA_MODE=true
+EOF
+chmod 600 /data/tracearr/.env
+chown -R tracearr:tracearr /data/tracearr
+msg_ok "Configured Tracearr"
+
+msg_info "Creating Services"
+cat </data/tracearr/prestart.sh
+#!/usr/bin/env bash
+# =============================================================================
+# Tune PostgreSQL for available resources (runs every startup)
+# =============================================================================
+# timescaledb-tune automatically optimizes PostgreSQL settings based on
+# available RAM and CPU. Safe to run repeatedly - recalculates if resources change.
+if command -v timescaledb-tune &> /dev/null; then
+ total_ram_kb=\$(grep MemTotal /proc/meminfo | awk '{print \$2}')
+ ram_for_tsdb=\$((total_ram_kb / 1024 / 2))
+ timescaledb-tune -yes -memory "\$ram_for_tsdb"MB --quiet 2>/dev/null \
+ || echo "Warning: timescaledb-tune failed (non-fatal)"
+fi
+# =============================================================================
+# Ensure TimescaleDB decompression limit is set (for existing databases)
+# =============================================================================
+# This setting allows migrations to modify compressed hypertable data.
+# Without it, bulk UPDATEs on compressed sessions will fail with
+# "tuple decompression limit exceeded" errors.
+pg_config_file="/etc/postgresql/18/main/postgresql.conf"
+if [ -f \$pg_config_file ]; then
+ if ! grep -q "max_tuples_decompressed_per_dml_transaction" \$pg_config_file; then
+ echo "" >> \$pg_config_file
+ echo "# Allow unlimited tuple decompression for migrations on compressed hypertables" >> \$pg_config_file
+ echo "timescaledb.max_tuples_decompressed_per_dml_transaction = 0" >> \$pg_config_file
+ fi
+fi
+systemctl restart postgresql
+EOF
+chmod +x /data/tracearr/prestart.sh
+cat </lib/systemd/system/tracearr.service
+[Unit]
+Description=Tracearr Web Server
+After=network.target postgresql.service redis-server.service
+
+[Service]
+Type=simple
+KillMode=control-group
+EnvironmentFile=/data/tracearr/.env
+WorkingDirectory=/opt/tracearr
+ExecStartPre=+/data/tracearr/prestart.sh
+ExecStart=node /opt/tracearr/apps/server/dist/index.js
+Restart=on-failure
+RestartSec=10
+User=tracearr
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now postgresql
+systemctl enable -q --now redis-server
+systemctl enable -q --now tracearr
+msg_ok "Created Services"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/ubuntu-install.sh b/install/ubuntu-install.sh
index 97283d838..80aee17c6 100644
--- a/install/ubuntu-install.sh
+++ b/install/ubuntu-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/install/unifi-os-server-install.sh b/install/unifi-os-server-install.sh
new file mode 100644
index 000000000..c094ee67c
--- /dev/null
+++ b/install/unifi-os-server-install.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: MickLesk (CanbiZ)
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://ui.com/
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+if [[ "${CTTYPE:-1}" != "0" ]]; then
+ msg_error "UniFi OS Server requires a privileged LXC container."
+ msg_error "Recreate the container with unprivileged=0."
+ exit 1
+fi
+
+if [[ ! -e /dev/net/tun ]]; then
+ msg_error "Missing /dev/net/tun in container."
+ msg_error "Enable TUN/TAP (var_tun=yes) or add /dev/net/tun passthrough."
+ exit 1
+fi
+
+msg_info "Installing dependencies"
+$STD apt install -y \
+ ca-certificates \
+ jq \
+ podman \
+ uidmap \
+ slirp4netns
+msg_ok "Installed dependencies"
+
+msg_info "Installing sysctl wrapper (ignore non-critical errors)"
+cat <<'EOF' >/usr/local/sbin/sysctl
+#!/bin/sh
+/usr/sbin/sysctl "$@" || true
+exit 0
+EOF
+chmod +x /usr/local/sbin/sysctl
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+msg_ok "Sysctl wrapper installed"
+
+msg_info "Fetching latest UniFi OS Server"
+API_URL="https://fw-update.ui.com/api/firmware-latest"
+TEMP_JSON="$(mktemp)"
+if ! curl -fsSL "$API_URL" -o "$TEMP_JSON"; then
+ rm -f "$TEMP_JSON"
+ msg_error "Failed to fetch data from Ubiquiti API"
+ exit 1
+fi
+LATEST=$(jq -r '
+ ._embedded.firmware
+ | map(select(.product == "unifi-os-server"))
+ | map(select(.platform == "linux-x64"))
+ | sort_by(.version_major, .version_minor, .version_patch)
+ | last
+' "$TEMP_JSON")
+UOS_VERSION=$(echo "$LATEST" | jq -r '.version' | sed 's/^v//')
+UOS_URL=$(echo "$LATEST" | jq -r '._links.data.href')
+rm -f "$TEMP_JSON"
+if [[ -z "$UOS_URL" || -z "$UOS_VERSION" || "$UOS_URL" == "null" ]]; then
+ msg_error "Failed to parse UniFi OS Server version or download URL"
+ exit 1
+fi
+msg_ok "Found UniFi OS Server ${UOS_VERSION}"
+
+msg_info "Downloading UniFi OS Server installer"
+mkdir -p /usr/local/sbin
+curl -fsSL "$UOS_URL" -o /usr/local/sbin/unifi-os-server.bin
+chmod +x /usr/local/sbin/unifi-os-server.bin
+msg_ok "Downloaded UniFi OS Server installer"
+
+msg_info "Installing UniFi OS Server (this takes a few minutes)"
+$STD /usr/local/sbin/unifi-os-server.bin <<<"y"
+msg_ok "UniFi OS Server installed"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/wishlist-install.sh b/install/wishlist-install.sh
new file mode 100644
index 000000000..5203d2731
--- /dev/null
+++ b/install/wishlist-install.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Dunky13
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://github.com/cmintey/wishlist
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing dependencies"
+$STD apt install -y \
+ build-essential \
+ python3 \
+ openssl \
+ caddy
+msg_ok "Installed dependencies"
+
+NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs
+fetch_and_deploy_gh_release "wishlist" "cmintey/wishlist" "tarball"
+LATEST_APP_VERSION=$(get_latest_github_release "cmintey/wishlist" false)
+import_local_ip
+
+msg_info "Installing Wishlist"
+cd /opt/wishlist
+cp .env.example .env
+sed -i "s|^ORIGIN=.*|ORIGIN=http://${LOCAL_IP}:3000|" /opt/wishlist/.env
+echo "NODE_ENV=production" >>/opt/wishlist/.env
+$STD pnpm install
+$STD pnpm svelte-kit sync
+$STD pnpm prisma generate
+sed -i 's|/usr/src/app/|/opt/wishlist/|g' $(grep -rl '/usr/src/app/' /opt/wishlist)
+export VERSION="v${LATEST_APP_VERSION}"
+export SHA="v${LATEST_APP_VERSION}"
+$STD pnpm run build
+$STD pnpm prune --prod
+chmod +x /opt/wishlist/entrypoint.sh
+mkdir -p /opt/wishlist/uploads
+mkdir -p /opt/wishlist/data
+msg_ok "Installed Wishlist"
+
+msg_info "Creating Service"
+cat </etc/systemd/system/wishlist.service
+[Unit]
+Description=Wishlist Service
+After=network.target
+
+[Service]
+WorkingDirectory=/opt/wishlist
+EnvironmentFile=/opt/wishlist/.env
+ExecStart=/usr/bin/env sh -c './entrypoint.sh'
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now wishlist
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/install/yubal-install.sh b/install/yubal-install.sh
new file mode 100644
index 000000000..c007e0317
--- /dev/null
+++ b/install/yubal-install.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: Crazywolf13
+# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
+# Source: https://github.com/guillevc/yubal
+
+source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
+color
+verb_ip6
+catch_errors
+setting_up_container
+network_check
+update_os
+
+msg_info "Installing Dependencies"
+$STD apt install -y \
+ build-essential \
+ libssl-dev \
+ libffi-dev \
+ python3-dev \
+ ffmpeg
+msg_ok "Installed Dependencies"
+
+msg_info "Installing Bun"
+export BUN_INSTALL=/opt/bun
+curl -fsSL https://bun.sh/install | $STD bash
+ln -sf /opt/bun/bin/bun /usr/local/bin/bun
+ln -sf /opt/bun/bin/bunx /usr/local/bin/bunx
+msg_ok "Installed Bun"
+
+UV_VERSION="0.7.19" PYTHON_VERSION="3.12" setup_uv
+
+msg_info "Installing Deno"
+$STD sh -c "curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh -s -- -y"
+msg_ok "Installed Deno"
+
+msg_info "Creating directories"
+mkdir -p /opt/yubal \
+ /opt/yubal_data \
+ /opt/yubal/ytdlp
+msg_ok "Created directories"
+
+fetch_and_deploy_gh_release "yubal" "guillevc/yubal" "tarball" "latest" "/opt/yubal"
+
+msg_info "Building Frontend"
+cd /opt/yubal/web
+$STD bun install --frozen-lockfile
+VERSION=$(get_latest_github_release "guillevc/yubal")
+VITE_VERSION=$VERSION VITE_COMMIT_SHA=$VERSION VITE_IS_RELEASE=true $STD bun run build
+msg_ok "Built Frontend"
+
+msg_info "Installing Python Dependencies"
+cd /opt/yubal
+export UV_CONCURRENT_DOWNLOADS=1
+$STD uv sync --no-dev --frozen
+msg_ok "Installed Python Dependencies"
+
+msg_info "Creating Service"
+cat </opt/yubal.env
+YUBAL_HOST=0.0.0.0
+YUBAL_PORT=8001
+YUBAL_DATA_DIR=/opt/yubal_data
+YUBAL_BEETS_DIR=/opt/yubal/beets
+YUBAL_YTDLP_DIR=/opt/yubal/ytdlp
+PYTHONUNBUFFERED=1
+EOF
+cat </etc/systemd/system/yubal.service
+[Unit]
+Description=Yubal
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/opt/yubal
+EnvironmentFile=/opt/yubal.env
+Environment="PATH=/opt/yubal/.venv/bin:/usr/local/bin:/usr/bin:/bin"
+ExecStart=/opt/yubal/.venv/bin/python -m yubal
+Restart=always
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+systemctl enable -q --now yubal
+msg_ok "Created Service"
+
+motd_ssh
+customize
+cleanup_lxc
diff --git a/misc/alpine-install.func b/misc/alpine-install.func
index 9c4169a40..0c2e9c587 100644
--- a/misc/alpine-install.func
+++ b/misc/alpine-install.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/misc/alpine-tools.func b/misc/alpine-tools.func
index 663b5f1d3..955554216 100644
--- a/misc/alpine-tools.func
+++ b/misc/alpine-tools.func
@@ -3,12 +3,165 @@
# Erwartet vorhandene msg_* und optional $STD aus deinem Framework.
+# Fallbacks, wenn core.func nicht geladen wurde (Alpine/ash-safe)
+if ! command -v msg_info >/dev/null 2>&1; then
+ msg_info() { echo "[INFO] $*"; }
+fi
+if ! command -v msg_ok >/dev/null 2>&1; then
+ msg_ok() { echo "[OK] $*"; }
+fi
+if ! command -v msg_warn >/dev/null 2>&1; then
+ msg_warn() { echo "[WARN] $*"; }
+fi
+if ! command -v msg_error >/dev/null 2>&1; then
+ msg_error() { echo "[ERROR] $*" >&2; }
+fi
+
# ------------------------------
# helpers
# ------------------------------
lower() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; }
has() { command -v "$1" >/dev/null 2>&1; }
+# tools.func compatibility helpers (Alpine-safe)
+cache_installed_version() {
+ local app="$1" version="$2"
+ mkdir -p /var/cache/app-versions
+ echo "$version" >"/var/cache/app-versions/${app}_version.txt"
+}
+
+get_cached_version() {
+ local app="$1"
+ mkdir -p /var/cache/app-versions
+ if [ -f "/var/cache/app-versions/${app}_version.txt" ]; then
+ cat "/var/cache/app-versions/${app}_version.txt"
+ return 0
+ fi
+ return 0
+}
+
+version_gt() {
+ # returns 0 if $1 > $2
+ # BusyBox-safe version compare
+ awk -v a="$1" -v b="$2" '
+ function splitver(v, arr) { n=split(v, arr, /\./); return n }
+ BEGIN {
+ na=splitver(a, A); nb=splitver(b, B);
+ n=(na>nb?na:nb);
+ for (i=1;i<=n;i++) {
+ va=(A[i]==""?0:A[i]); vb=(B[i]==""?0:B[i]);
+ if (va+0 > vb+0) exit 0;
+ if (va+0 < vb+0) exit 1;
+ }
+ exit 1;
+ }'
+}
+
+get_system_arch() {
+ local arch
+ arch=$(uname -m 2>/dev/null || echo "")
+ [ "$arch" = "x86_64" ] && arch="amd64"
+ [ "$arch" = "aarch64" ] && arch="arm64"
+ echo "$arch"
+}
+
+create_temp_dir() {
+ mktemp -d
+}
+
+get_os_info() {
+ local field="${1:-all}"
+ [ -z "${_OS_ID:-}" ] && _OS_ID=$(awk -F= '/^ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
+ [ -z "${_OS_CODENAME:-}" ] && _OS_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
+ [ -z "${_OS_VERSION:-}" ] && _OS_VERSION=$(awk -F= '/^VERSION_ID=/{gsub(/"/,"",$2); print $2}' /etc/os-release 2>/dev/null)
+ case "$field" in
+ id) echo "$_OS_ID" ;;
+ codename) echo "$_OS_CODENAME" ;;
+ version | version_id) echo "$_OS_VERSION" ;;
+ all) echo "ID=$_OS_ID CODENAME=$_OS_CODENAME VERSION=$_OS_VERSION" ;;
+ *) echo "$_OS_ID" ;;
+ esac
+}
+
+is_alpine() { [ "$(get_os_info id)" = "alpine" ]; }
+
+get_os_version_major() {
+ local v
+ v=$(get_os_info version)
+ echo "${v%%.*}"
+}
+
+ensure_dependencies() {
+ need_tool "$@"
+}
+
+download_file() {
+ local url="$1" output="$2" max_retries="${3:-3}" show_progress="${4:-false}"
+ local i=1 curl_opts="-fsSL"
+ [ "$show_progress" = "true" ] && curl_opts="-fL#"
+ while [ $i -le "$max_retries" ]; do
+ if curl $curl_opts -o "$output" "$url"; then
+ return 0
+ fi
+ i=$((i + 1))
+ [ $i -le "$max_retries" ] && sleep 2
+ done
+ msg_error "Failed to download: $url"
+ return 1
+}
+
+github_api_call() {
+ local url="$1" output_file="${2:-/dev/stdout}"
+ local max_retries=3 retry_delay=2 attempt=1
+ local header=""
+ [ -n "${GITHUB_TOKEN:-}" ] && header="-H Authorization:Bearer\ ${GITHUB_TOKEN}"
+ while [ $attempt -le $max_retries ]; do
+ http_code=$(curl -fsSL -w "%{http_code}" -o "$output_file" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ $header "$url" 2>/dev/null || echo 000)
+ case "$http_code" in
+ 200) return 0 ;;
+ 403) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || {
+ msg_error "GitHub API rate limit exceeded"
+ return 1
+ } ;;
+ 404)
+ msg_error "GitHub API endpoint not found: $url"
+ return 1
+ ;;
+ *) [ $attempt -lt $max_retries ] && sleep "$retry_delay" || {
+ msg_error "GitHub API call failed with HTTP $http_code"
+ return 1
+ } ;;
+ esac
+ retry_delay=$((retry_delay * 2))
+ attempt=$((attempt + 1))
+ done
+ return 1
+}
+
+extract_version_from_json() {
+ local json="$1" field="${2:-tag_name}" strip_v="${3:-true}" version
+ need_tool jq || return 1
+ version=$(printf '%s' "$json" | jq -r ".${field} // empty")
+ [ -z "$version" ] && return 1
+ [ "$strip_v" = "true" ] && printf '%s' "${version#v}" || printf '%s' "$version"
+}
+
+get_latest_github_release() {
+ local repo="$1" strip_v="${2:-true}" tmp
+ tmp=$(mktemp) || return 1
+ github_api_call "https://api.github.com/repos/${repo}/releases/latest" "$tmp" || {
+ rm -f "$tmp"
+ return 1
+ }
+ extract_version_from_json "$(cat "$tmp")" "tag_name" "$strip_v"
+ rc=$?
+ rm -f "$tmp"
+ return $rc
+}
+
need_tool() {
# usage: need_tool curl jq unzip ...
# setup missing tools via apk
@@ -78,7 +231,12 @@ check_for_gh_release() {
}
need_tool curl jq || return 1
- tag=$(curl -fsSL "https://api.github.com/repos/${source}/releases/latest" | jq -r '.tag_name // empty')
+ github_api_call "https://api.github.com/repos/${source}/releases/latest" "/tmp/${app_lc}-release.json" || {
+ msg_error "Unable to fetch latest tag for $app"
+ return 1
+ }
+ tag=$(cat "/tmp/${app_lc}-release.json" | jq -r '.tag_name // empty')
+ rm -f "/tmp/${app_lc}-release.json"
[ -z "$tag" ] && {
msg_error "Unable to fetch latest tag for $app"
return 1
@@ -115,7 +273,7 @@ check_for_gh_release() {
# GitHub: get Release & deployen (Alpine)
# modes: tarball | prebuild | singlefile
# ------------------------------
-fetch_and_deploy_gh() {
+fetch_and_deploy_gh_release() {
# $1 app, $2 repo, [$3 mode], [$4 version], [$5 target], [$6 asset_pattern
local app="$1" repo="$2" mode="${3:-tarball}" version="${4:-latest}" target="${5:-/opt/$1}" pattern="${6:-}"
local app_lc
@@ -133,20 +291,21 @@ fetch_and_deploy_gh() {
tmpd="$(mktemp -d)" || return 1
mkdir -p "$target"
- # Release JSON
+ # Release JSON (with token/rate-limit handling)
if [ "$version" = "latest" ]; then
- json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/latest")" || {
+ github_api_call "https://api.github.com/repos/$repo/releases/latest" "$tmpd/release.json" || {
msg_error "GitHub API failed"
rm -rf "$tmpd"
return 1
}
else
- json="$(curl -fsSL "https://api.github.com/repos/$repo/releases/tags/$version")" || {
+ github_api_call "https://api.github.com/repos/$repo/releases/tags/$version" "$tmpd/release.json" || {
msg_error "GitHub API failed"
rm -rf "$tmpd"
return 1
}
fi
+ json="$(cat "$tmpd/release.json")"
# correct Version
version="$(printf '%s' "$json" | jq -r '.tag_name // empty')"
@@ -173,6 +332,7 @@ fetch_and_deploy_gh() {
return 1
}
unpack="$(find "$tmpd" -mindepth 1 -maxdepth 1 -type d | head -n1)"
+ [ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
# copy content of unpack to target
(cd "$unpack" && tar -cf - .) | (cd "$target" && tar -xf -) || {
msg_error "copy failed"
@@ -180,6 +340,34 @@ fetch_and_deploy_gh() {
return 1
}
;;
+ binary)
+ [ -n "$pattern" ] || pattern="*.apk"
+ url="$(printf '%s' "$json" | jq -r '.assets[].browser_download_url' | awk -v p="$pattern" 'BEGIN{IGNORECASE=1} $0 ~ p {print; exit}')"
+ [ -z "$url" ] && {
+ msg_error "binary asset not found for pattern: $pattern"
+ rm -rf "$tmpd"
+ return 1
+ }
+ filename="${url##*/}"
+ download_with_progress "$url" "$tmpd/$filename" || {
+ rm -rf "$tmpd"
+ return 1
+ }
+ case "$filename" in
+ *.apk)
+ apk add --no-cache --allow-untrusted "$tmpd/$filename" >/dev/null 2>&1 || {
+ msg_error "apk install failed: $filename"
+ rm -rf "$tmpd"
+ return 1
+ }
+ ;;
+ *)
+ msg_error "Unsupported binary asset on Alpine: $filename"
+ rm -rf "$tmpd"
+ return 1
+ ;;
+ esac
+ ;;
prebuild)
[ -n "$pattern" ] || {
msg_error "prebuild requires asset pattern"
@@ -220,6 +408,7 @@ fetch_and_deploy_gh() {
return 1
;;
esac
+ [ "${CLEAN_INSTALL:-0}" = "1" ] && rm -rf "${target:?}/"*
# top-level folder strippen
if [ "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ] && [ -z "$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type f | head -n1)" ]; then
unpack="$(find "$tmpd/unp" -mindepth 1 -maxdepth 1 -type d)"
@@ -252,11 +441,13 @@ fetch_and_deploy_gh() {
return 1
}
filename="${url##*/}"
- download_with_progress "$url" "$target/$app" || {
+ local target_file="$app"
+ [ "${USE_ORIGINAL_FILENAME:-false}" = "true" ] && target_file="$filename"
+ download_with_progress "$url" "$target/$target_file" || {
rm -rf "$tmpd"
return 1
}
- chmod +x "$target/$app"
+ chmod +x "$target/$target_file"
;;
*)
msg_error "Unknown mode: $mode"
@@ -271,6 +462,11 @@ fetch_and_deploy_gh() {
msg_ok "Deployed $app ($version) β $target"
}
+# tools.func compatibility alias
+fetch_and_deploy_gh() {
+ fetch_and_deploy_gh_release "$@"
+}
+
# ------------------------------
# yq (mikefarah) β Alpine
# ------------------------------
diff --git a/misc/api.func b/misc/api.func
index cae06c153..f6f284bec 100644
--- a/misc/api.func
+++ b/misc/api.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
diff --git a/misc/bak_december/build.func.pve9-update b/misc/bak_december/build.func.pve9-update
index 8583b8fa1..7ce1537a6 100644
--- a/misc/bak_december/build.func.pve9-update
+++ b/misc/bak_december/build.func.pve9-update
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
# Revision: 1
diff --git a/misc/bak_december/install copy.func b/misc/bak_december/install copy.func
index e9e319576..2abfccdf8 100644
--- a/misc/bak_december/install copy.func
+++ b/misc/bak_december/install copy.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
diff --git a/misc/bak_december/install.func.bak b/misc/bak_december/install.func.bak
index f72e080b7..5d6244550 100644
--- a/misc/bak_december/install.func.bak
+++ b/misc/bak_december/install.func.bak
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
diff --git a/misc/bak_december/install.func.unified b/misc/bak_december/install.func.unified
index 14f5f7c02..c222061ac 100644
--- a/misc/bak_december/install.func.unified
+++ b/misc/bak_december/install.func.unified
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
diff --git a/misc/build.func b/misc/build.func
index 7ce994d1e..06923e925 100644
--- a/misc/build.func
+++ b/misc/build.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk | michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
# Revision: 1
@@ -311,7 +311,10 @@ update_motd_ip() {
# - Falls back to warning if no keys provided
# ------------------------------------------------------------------------------
install_ssh_keys_into_ct() {
- [[ "$SSH" != "yes" ]] && return 0
+ [[ "${SSH:-no}" != "yes" ]] && return 0
+
+ # Ensure SSH_KEYS_FILE is defined (may not be set if advanced_settings was skipped)
+ : "${SSH_KEYS_FILE:=}"
if [[ -n "$SSH_KEYS_FILE" && -s "$SSH_KEYS_FILE" ]]; then
msg_info "Installing selected SSH keys into CT ${CTID}"
@@ -394,6 +397,90 @@ find_host_ssh_keys() {
)
}
+# ==============================================================================
+# SECTION 3B: IP RANGE SCANNING
+# ==============================================================================
+
+# ------------------------------------------------------------------------------
+# ip_to_int() / int_to_ip()
+#
+# - Converts IP address to integer and vice versa for range iteration
+# ------------------------------------------------------------------------------
+ip_to_int() {
+ local IFS=.
+ read -r i1 i2 i3 i4 <<<"$1"
+ echo $(((i1 << 24) + (i2 << 16) + (i3 << 8) + i4))
+}
+
+int_to_ip() {
+ local ip=$1
+ echo "$(((ip >> 24) & 0xFF)).$(((ip >> 16) & 0xFF)).$(((ip >> 8) & 0xFF)).$((ip & 0xFF))"
+}
+
+# ------------------------------------------------------------------------------
+# resolve_ip_from_range()
+#
+# - Takes an IP range in format "10.0.0.1/24-10.0.0.10/24"
+# - Pings each IP in the range to find the first available one
+# - Returns the first free IP with CIDR notation
+# - Sets NET_RESOLVED to the resolved IP or empty on failure
+# ------------------------------------------------------------------------------
+resolve_ip_from_range() {
+ local range="$1"
+ local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
+ local ip_start ip_end
+
+ # Parse range: "10.0.0.1/24-10.0.0.10/24"
+ ip_start="${range%%-*}"
+ ip_end="${range##*-}"
+
+ if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
+ NET_RESOLVED=""
+ return 1
+ fi
+
+ local ip1="${ip_start%%/*}"
+ local ip2="${ip_end%%/*}"
+ local cidr="${ip_start##*/}"
+
+ local start_int=$(ip_to_int "$ip1")
+ local end_int=$(ip_to_int "$ip2")
+
+ for ((ip_int = start_int; ip_int <= end_int; ip_int++)); do
+ local ip=$(int_to_ip $ip_int)
+ msg_info "Checking IP: $ip"
+ if ! ping -c 1 -W 1 "$ip" >/dev/null 2>&1; then
+ NET_RESOLVED="$ip/$cidr"
+ msg_ok "Found free IP: ${BGN}$NET_RESOLVED${CL}"
+ return 0
+ fi
+ done
+
+ NET_RESOLVED=""
+ msg_error "No free IP found in range $range"
+ return 1
+}
+
+# ------------------------------------------------------------------------------
+# is_ip_range()
+#
+# - Checks if a string is an IP range (contains - and looks like IP/CIDR)
+# - Returns 0 if it's a range, 1 otherwise
+# ------------------------------------------------------------------------------
+is_ip_range() {
+ local value="$1"
+ local ip_start ip_end
+ if [[ "$value" == *-* ]] && [[ "$value" != "dhcp" ]]; then
+ local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
+ ip_start="${value%%-*}"
+ ip_end="${value##*-}"
+ if [[ "$ip_start" =~ $ip_cidr_regex ]] && [[ "$ip_end" =~ $ip_cidr_regex ]]; then
+ return 0
+ fi
+ fi
+ return 1
+}
+
# ==============================================================================
# SECTION 4: STORAGE & RESOURCE MANAGEMENT
# ==============================================================================
@@ -506,6 +593,18 @@ base_settings() {
HN=${var_hostname:-$NSAPP}
BRG=${var_brg:-"vmbr0"}
NET=${var_net:-"dhcp"}
+
+ # Resolve IP range if NET contains a range (e.g., 192.168.1.100/24-192.168.1.200/24)
+ if is_ip_range "$NET"; then
+ msg_info "Scanning IP range: $NET"
+ if resolve_ip_from_range "$NET"; then
+ NET="$NET_RESOLVED"
+ else
+ msg_error "Could not find free IP in range. Falling back to DHCP."
+ NET="dhcp"
+ fi
+ fi
+
IPV6_METHOD=${var_ipv6_method:-"none"}
IPV6_STATIC=${var_ipv6_static:-""}
GATE=${var_gateway:-""}
@@ -535,9 +634,16 @@ base_settings() {
TAGS="community-script,${var_tags:-}"
ENABLE_FUSE=${var_fuse:-"${1:-no}"}
ENABLE_TUN=${var_tun:-"${1:-no}"}
- ENABLE_KEYCTL=${var_keyctl:-0}
- ENABLE_MKNOD=${var_mknod:-0}
+
+ # Additional settings that may be skipped if advanced_settings is not run (e.g., App Defaults)
+ ENABLE_GPU=${var_gpu:-"no"}
+ ENABLE_NESTING=${var_nesting:-"1"}
+ ENABLE_KEYCTL=${var_keyctl:-"0"}
+ ENABLE_MKNOD=${var_mknod:-"0"}
MOUNT_FS=${var_mount_fs:-""}
+ PROTECT_CT=${var_protection:-"no"}
+ CT_TIMEZONE=${var_timezone:-"$timezone"}
+ [[ "${CT_TIMEZONE:-}" == Etc/* ]] && CT_TIMEZONE="host" # pct doesn't accept Etc/* zones
# Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
if [ -z "$var_os" ]; then
@@ -587,6 +693,13 @@ load_vars_file() {
[[ "$var_key" != var_* ]] && continue
_is_whitelisted "$var_key" || continue
+ # Strip inline comments (everything after unquoted #)
+ # Handle: var=value # comment OR var="value" # comment
+ if [[ ! "$var_val" =~ ^[\"\'] ]]; then
+ # Unquoted value: strip from first #
+ var_val="${var_val%%#*}"
+ fi
+
# Strip quotes
if [[ "$var_val" =~ ^\"(.*)\"$ ]]; then
var_val="${BASH_REMATCH[1]}"
@@ -594,6 +707,9 @@ load_vars_file() {
var_val="${BASH_REMATCH[1]}"
fi
+ # Trim trailing whitespace
+ var_val="${var_val%"${var_val##*[![:space:]]}"}"
+
# Set only if not already exported
[[ -z "${!var_key+x}" ]] && export "${var_key}=${var_val}"
fi
@@ -696,12 +812,18 @@ var_fuse=no
var_tun=no
# Advanced Settings (Proxmox-official features)
+# var_nesting: Allow nesting (required for Docker/LXC in CT)
var_nesting=1
+# var_keyctl: Allow keyctl() - needed for Docker (systemd-networkd workaround)
var_keyctl=0
+# var_mknod: Allow device node creation (requires kernel 5.3+, experimental)
var_mknod=0
-var_mount_fs=""
+# var_mount_fs: Allow specific filesystems: nfs,fuse,ext4,etc (leave empty for defaults)
+var_mount_fs=
+# var_protection: Prevent accidental deletion of container
var_protection=no
-var_timezone=""
+# var_timezone: Container timezone (e.g. Europe/Berlin, leave empty for host timezone)
+var_timezone=
var_tags=community-script
var_verbose=no
@@ -3124,6 +3246,9 @@ EOF'
;;
debian | ubuntu | devuan)
+ # First install locales package (required for locale-gen on minimal templates)
+ pct exec "$CTID" -- bash -c "apt-get update >/dev/null && apt-get install -y locales >/dev/null 2>&1 || true"
+
# Locale setup for Debian-based
pct exec "$CTID" -- bash -c "sed -i '/$LANG/ s/^# //' /etc/locale.gen 2>/dev/null || true"
pct exec "$CTID" -- bash -c "locale_line=\$(grep -v '^#' /etc/locale.gen 2>/dev/null | grep -E '^[a-zA-Z]' | awk '{print \$1}' | head -n 1) && \
@@ -3150,33 +3275,128 @@ EOF'
fedora | rockylinux | almalinux | centos)
# RHEL-based: Fedora, Rocky, AlmaLinux, CentOS
- pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq procps-ng >/dev/null 2>&1 || yum install -y curl sudo mc jq procps-ng >/dev/null 2>&1" || {
- msg_error "dnf/yum base packages installation failed"
- exit 1
- }
+ # Detect OS major version for EL10+ compatibility (DNF 5, different packages)
+ local rhel_version
+ rhel_version=$(pct exec "$CTID" -- bash -c "grep -oP '(?<=VERSION_ID=\")[0-9]+' /etc/os-release 2>/dev/null || echo 9")
+
+ # First run makecache to ensure repos are ready (critical for fresh templates)
+ msg_info "Initializing package manager (this may take a moment)..."
+ if ! pct exec "$CTID" -- bash -c "dnf makecache --refresh 2>&1 || yum makecache 2>&1" >/dev/null 2>&1; then
+ msg_warn "Package cache update had issues, continuing anyway..."
+ fi
+
+ # Build package list - EL10+ may not have glibc-langpack-en in same form
+ local rhel_packages="curl sudo mc jq procps-ng ncurses"
+ if [[ "$rhel_version" -lt 10 ]]; then
+ rhel_packages="$rhel_packages glibc-langpack-en"
+ else
+ # EL10 uses glibc-all-langpacks or langpacks-en
+ rhel_packages="$rhel_packages langpacks-en glibc-all-langpacks"
+ fi
+
+ # Install base packages with better error handling
+ local install_log="/tmp/dnf_install_${CTID}.log"
+ if ! pct exec "$CTID" -- bash -c "dnf install -y $rhel_packages 2>&1 | tee $install_log; exit \${PIPESTATUS[0]}" >/dev/null 2>&1; then
+ # Check if it's just missing optional packages
+ if pct exec "$CTID" -- bash -c "rpm -q curl sudo mc jq procps-ng" >/dev/null 2>&1; then
+ msg_warn "Some optional packages may have failed, but core packages installed"
+ else
+ # Real failure - try minimal install
+ msg_warn "Full package install failed, trying minimal set..."
+ if ! pct exec "$CTID" -- bash -c "dnf install -y curl sudo jq 2>&1" >/dev/null 2>&1; then
+ msg_error "dnf/yum base packages installation failed"
+ pct exec "$CTID" -- bash -c "cat $install_log 2>/dev/null" || true
+ exit 1
+ fi
+ fi
+ fi
+
+ # Set locale for RHEL-based systems
+ pct exec "$CTID" -- bash -c "localectl set-locale LANG=en_US.UTF-8 2>/dev/null || echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
+
+ # Timezone setup for RHEL
+ if [[ -z "${tz:-}" ]]; then
+ tz=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "Etc/UTC")
+ fi
+ [[ "${tz:-}" == Etc/* ]] && tz="UTC"
+ if pct exec "$CTID" -- test -e "/usr/share/zoneinfo/$tz"; then
+ pct exec "$CTID" -- bash -c "timedatectl set-timezone '$tz' 2>/dev/null || ln -sf '/usr/share/zoneinfo/$tz' /etc/localtime" || true
+ fi
;;
opensuse)
- # openSUSE
- pct exec "$CTID" -- bash -c "zypper --non-interactive install curl sudo mc jq >/dev/null" || {
- msg_error "zypper base packages installation failed"
- exit 1
- }
+ # openSUSE - special handling for terminal/locale issues
+ # Use --gpg-auto-import-keys to avoid interactive prompts that cause hangs
+ msg_info "Initializing package manager for openSUSE..."
+ pct exec "$CTID" -- bash -c "zypper --gpg-auto-import-keys --non-interactive refresh 2>&1" >/dev/null 2>&1 || true
+
+ # Install packages - ncurses and terminfo are CRITICAL for terminal to work
+ if ! pct exec "$CTID" -- bash -c "zypper --gpg-auto-import-keys --non-interactive install -y curl sudo mc jq glibc-locale ncurses terminfo-base 2>&1" >/dev/null 2>&1; then
+ # Try without glibc-locale
+ if ! pct exec "$CTID" -- bash -c "zypper --gpg-auto-import-keys --non-interactive install -y curl sudo mc jq ncurses terminfo-base 2>&1" >/dev/null 2>&1; then
+ msg_error "zypper base packages installation failed"
+ exit 1
+ fi
+ fi
+
+ # Fix 'unknown terminal type' error - set TERM in multiple places
+ pct exec "$CTID" -- bash -c "localectl set-locale LANG=en_US.UTF-8 2>/dev/null || echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
+
+ # Set TERM globally for all users
+ pct exec "$CTID" -- bash -c "cat > /etc/profile.d/term.sh << 'EOFTERM'
+# Fix terminal type for LXC containers
+if [ -z \"\$TERM\" ] || [ \"\$TERM\" = \"dumb\" ] || [ \"\$TERM\" = \"-\" ]; then
+ export TERM=xterm-256color
+fi
+EOFTERM
+chmod +x /etc/profile.d/term.sh" || true
+
+ # Also set in /etc/environment for non-login shells
+ pct exec "$CTID" -- bash -c "grep -q '^TERM=' /etc/environment 2>/dev/null || echo 'TERM=xterm-256color' >> /etc/environment" || true
;;
gentoo)
- # Gentoo - emerge is slow, only install essentials
- pct exec "$CTID" -- bash -c "emerge --quiet app-misc/jq net-misc/curl app-misc/mc >/dev/null 2>&1" || {
- msg_warn "Gentoo base packages installation incomplete - may need manual setup"
+ # Gentoo - OpenRC based, emerge is slow
+ # Use emerge-webrsync (faster, uses http instead of rsync)
+ msg_info "Syncing Gentoo portage via webrsync (faster than rsync)..."
+ pct exec "$CTID" -- bash -c "emerge-webrsync 2>&1" >/dev/null 2>&1 || {
+ msg_warn "emerge-webrsync failed, trying emerge --sync..."
+ pct exec "$CTID" -- bash -c "emerge --sync 2>&1" >/dev/null 2>&1 || true
}
+
+ # Install curl FIRST - it's required for install.func to work
+ msg_info "Installing essential packages for Gentoo..."
+ if ! pct exec "$CTID" -- bash -c "emerge --quiet --noreplace net-misc/curl 2>&1" >/dev/null 2>&1; then
+ msg_error "Failed to install curl on Gentoo - this is required"
+ exit 1
+ fi
+
+ # Install remaining packages
+ pct exec "$CTID" -- bash -c "emerge --quiet --noreplace app-misc/jq app-misc/mc sys-libs/ncurses 2>&1" >/dev/null 2>&1 || {
+ msg_warn "Some Gentoo packages may need manual setup"
+ }
+
+ # Set TERM for Gentoo
+ pct exec "$CTID" -- bash -c "echo 'export TERM=xterm-256color' >> /etc/profile.d/term.sh && chmod +x /etc/profile.d/term.sh" || true
;;
openeuler)
- # openEuler (RHEL-compatible)
- pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq >/dev/null" || {
- msg_error "dnf base packages installation failed"
- exit 1
- }
+ # openEuler (RHEL-compatible, uses DNF)
+ # Note: Template was patched with /etc/redhat-release in create_container
+ msg_info "Initializing package manager for openEuler..."
+ pct exec "$CTID" -- bash -c "dnf makecache --refresh 2>&1" >/dev/null 2>&1 || true
+
+ # openEuler package names may differ from RHEL
+ local euler_packages="curl sudo mc jq procps-ng ncurses"
+ if ! pct exec "$CTID" -- bash -c "dnf install -y $euler_packages 2>&1" >/dev/null 2>&1; then
+ # Try without procps-ng (might be just 'procps' in openEuler)
+ if ! pct exec "$CTID" -- bash -c "dnf install -y curl sudo mc jq ncurses 2>&1" >/dev/null 2>&1; then
+ msg_error "dnf base packages installation failed"
+ exit 1
+ fi
+ fi
+ # Set locale
+ pct exec "$CTID" -- bash -c "echo 'LANG=en_US.UTF-8' > /etc/locale.conf" || true
;;
*)
@@ -3199,7 +3419,7 @@ EOF'
set +Eeuo pipefail # Disable ALL error handling temporarily
trap - ERR # Remove ERR trap completely
- lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/install/${var_install}.sh)"
+ lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/install/${var_install}.sh)"
local lxc_exit=$?
set -Eeuo pipefail # Re-enable error handling
@@ -3286,7 +3506,7 @@ EOF'
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
echo -e "${TAB}${HOLD}${DGN}Setting up MOTD and SSH for debugging...${CL}"
if pct exec "$CTID" -- bash -c "
- source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/install.func)
+ source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/misc/install.func)
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
" >/dev/null 2>&1; then
local ct_ip=$(pct exec "$CTID" ip a s dev eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
@@ -3723,12 +3943,19 @@ create_lxc_container() {
# Template discovery & validation
# Supported OS types (pveam available): alpine, almalinux, centos, debian,
# devuan, fedora, gentoo, openeuler, opensuse, rockylinux, ubuntu
+ # Template naming conventions:
+ # - Debian/Ubuntu/Devuan: --standard__.tar.zst
+ # - Alpine/Fedora/Rocky/CentOS/AlmaLinux/openEuler: --default__.tar.xz
+ # - Gentoo: gentoo-current-openrc__.tar.xz (note: underscore before date!)
+ # - openSUSE: opensuse--default__.tar.xz
+ # - CentOS: centos--stream-default__.tar.xz (note: stream in name)
# ------------------------------------------------------------------------------
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
case "$PCT_OSTYPE" in
debian | ubuntu | devuan) TEMPLATE_PATTERN="-standard_" ;;
- alpine | fedora | rocky | rockylinux | centos | almalinux | openeuler) TEMPLATE_PATTERN="-default_" ;;
- gentoo) TEMPLATE_PATTERN="-current_" ;;
+ alpine | fedora | rockylinux | almalinux | openeuler) TEMPLATE_PATTERN="-default_" ;;
+ centos) TEMPLATE_PATTERN="-stream-default_" ;;
+ gentoo) TEMPLATE_PATTERN="-openrc_" ;; # Pattern: gentoo-current-openrc_ (underscore!)
opensuse) TEMPLATE_PATTERN="-default_" ;;
*) TEMPLATE_PATTERN="" ;;
esac
@@ -3790,14 +4017,27 @@ create_lxc_container() {
echo "[DEBUG] No template found for ${PCT_OSTYPE} ${PCT_OSVERSION}, searching for alternatives..."
# Get all available versions for this OS type
- mapfile -t AVAILABLE_VERSIONS < <(
- pveam available -section system 2>/dev/null |
- grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
- awk -F'\t' '{print $1}' |
- grep "^${PCT_OSTYPE}-" |
- sed -E "s/.*${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
- sort -u -V 2>/dev/null
- )
+ # Special handling for Gentoo which uses 'current' instead of numeric version
+ if [[ "$PCT_OSTYPE" == "gentoo" ]]; then
+ mapfile -t AVAILABLE_VERSIONS < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk '{print $2}' |
+ grep "^gentoo-" |
+ sed -E 's/gentoo-([^-]+)-.*/\1/' |
+ sort -u 2>/dev/null || sort -u
+ )
+ else
+ mapfile -t AVAILABLE_VERSIONS < <(
+ pveam available -section system 2>/dev/null |
+ grep -E '\.(tar\.zst|tar\.xz|tar\.gz)$' |
+ awk '{print $2}' |
+ grep "^${PCT_OSTYPE}-" |
+ sed -E "s/${PCT_OSTYPE}-([0-9]+(\.[0-9]+)?).*/\1/" |
+ grep -E '^[0-9]' |
+ sort -u -V 2>/dev/null || sort -u
+ )
+ fi
if [[ ${#AVAILABLE_VERSIONS[@]} -gt 0 ]]; then
echo ""
@@ -4043,6 +4283,43 @@ create_lxc_container() {
LOGFILE="/tmp/pct_create_${CTID}_$(date +%Y%m%d_%H%M%S)_${SESSION_ID}.log"
+ # ------------------------------------------------------------------------------
+ # openEuler Template Patch: Create /etc/redhat-release inside template
+ # PVE's post_create_hook expects this file for RHEL-family OS detection
+ # Without it, container creation fails with "error in setup task"
+ # ------------------------------------------------------------------------------
+ if [[ "${var_os:-}" == "openeuler" ]]; then
+ msg_info "Patching openEuler template for PVE compatibility..."
+ local TEMP_EXTRACT_DIR="/tmp/openeuler_template_patch_$$"
+ local PATCHED_TEMPLATE="${TEMPLATE_PATH%.tar.xz}_patched.tar.xz"
+
+ # Only patch if not already patched
+ if [[ ! -f "$PATCHED_TEMPLATE" ]]; then
+ mkdir -p "$TEMP_EXTRACT_DIR"
+
+ # Extract template
+ if tar -xf "$TEMPLATE_PATH" -C "$TEMP_EXTRACT_DIR" 2>/dev/null; then
+ # Create /etc/redhat-release if it doesn't exist
+ if [[ ! -f "$TEMP_EXTRACT_DIR/etc/redhat-release" ]]; then
+ echo "openEuler release ${var_version:-25.03}" >"$TEMP_EXTRACT_DIR/etc/redhat-release"
+ fi
+
+ # Repack template
+ if tar -cJf "$PATCHED_TEMPLATE" -C "$TEMP_EXTRACT_DIR" . 2>/dev/null; then
+ # Replace original with patched version
+ mv "$PATCHED_TEMPLATE" "$TEMPLATE_PATH"
+ msg_ok "openEuler template patched successfully"
+ else
+ msg_warn "Failed to repack template, trying without patch..."
+ fi
+ else
+ msg_warn "Failed to extract template for patching, trying without patch..."
+ fi
+
+ rm -rf "$TEMP_EXTRACT_DIR"
+ fi
+ fi
+
# # DEBUG: Show the actual command that will be executed
# echo "[DEBUG] ===== PCT CREATE COMMAND DETAILS ====="
# echo "[DEBUG] CTID: $CTID"
diff --git a/misc/cloud-init.func b/misc/cloud-init.func
index 9a5ca45e0..f4d570ee7 100644
--- a/misc/cloud-init.func
+++ b/misc/cloud-init.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts ORG
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/branch/main/LICENSE
# Revision: 1
diff --git a/misc/core.func b/misc/core.func
index 39d655b0e..8c2bf008e 100644
--- a/misc/core.func
+++ b/misc/core.func
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/LICENSE
# ==============================================================================
@@ -523,8 +523,11 @@ msg_info() {
if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then
declare -gA MSG_INFO_SHOWN=()
fi
- [[ -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
- MSG_INFO_SHOWN["$msg"]=1
+ # Sanitize message for use as associative array key (remove ANSI codes and special chars)
+ local sanitized_msg
+ sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
+ [[ -n "${MSG_INFO_SHOWN["$sanitized_msg"]+x}" ]] && return
+ MSG_INFO_SHOWN["$sanitized_msg"]=1
stop_spinner
SPINNER_MSG="$msg"
@@ -569,7 +572,10 @@ msg_ok() {
stop_spinner
clear_line
echo -e "$CM ${GN}${msg}${CL}"
- unset MSG_INFO_SHOWN["$msg"]
+ # Sanitize message for use as associative array key (remove ANSI codes and special chars)
+ local sanitized_msg
+ sanitized_msg=$(printf '%s' "$msg" | sed 's/\x1b\[[0-9;]*m//g; s/[^a-zA-Z0-9_]/_/g')
+ unset 'MSG_INFO_SHOWN['"$sanitized_msg"']' 2>/dev/null || true
}
# ------------------------------------------------------------------------------
diff --git a/misc/error_handler.func b/misc/error_handler.func
index afbc9e1c5..9af40f0fa 100644
--- a/misc/error_handler.func
+++ b/misc/error_handler.func
@@ -2,7 +2,7 @@
# ------------------------------------------------------------------------------
# ERROR HANDLER - ERROR & SIGNAL MANAGEMENT
# ------------------------------------------------------------------------------
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# ------------------------------------------------------------------------------
diff --git a/misc/install.func b/misc/install.func
index f474b4062..c8d6ae7e1 100644
--- a/misc/install.func
+++ b/misc/install.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
@@ -551,12 +551,12 @@ get_ip() {
# Try hostname -I first (most common)
if command -v hostname &>/dev/null; then
- ip=$(hostname -I 2>/dev/null | awk '{print $1}')
+ ip=$(hostname -I 2>/dev/null | awk '{print $1}' || true)
fi
# Fallback to ip command
if [[ -z "$ip" ]] && command -v ip &>/dev/null; then
- ip=$(ip -4 addr show scope global | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)
+ ip=$(ip -4 addr show scope global | awk '/inet /{print $2}' | cut -d/ -f1 | head -1)
fi
# Fallback to ifconfig
@@ -780,7 +780,7 @@ echo -e "${BOLD:-}${YW:-}${APPLICATION:-Container} LXC Container - DEV Repositor
echo -e "${RD:-}WARNING: This is a DEVELOPMENT version (ProxmoxVED). Do NOT use in production!${CL:-}"
echo -e "${YW:-} OS: ${GN:-}${os_name} - Version: ${os_version}${CL:-}"
echo -e "${YW:-} Hostname: ${GN:-}\$(hostname)${CL:-}"
-echo -e "${YW:-} IP Address: ${GN:-}\$(hostname -I 2>/dev/null | awk '{print \$1}' || ip -4 addr show scope global | grep -oP '(?<=inet\s)\\d+(\\.\\d+){3}' | head -1)${CL:-}"
+echo -e "${YW:-} IP Address: ${GN:-}\$(hostname -I 2>/dev/null | awk '{print \$1}' || ip -4 addr show scope global | awk '/inet /{print \$2}' | cut -d/ -f1 | head -1)${CL:-}"
echo -e "${YW:-} Repository: ${GN:-}https://github.com/community-scripts/ProxmoxVED${CL:-}"
echo ""
EOF
@@ -867,7 +867,7 @@ customize() {
cat >/etc/systemd/system/console-getty.service.d/override.conf <<'EOF'
[Service]
ExecStart=
-ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud 115200,38400,9600 $TERM
+ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud 115200,38400,9600 - $TERM
EOF
# Enable console-getty for LXC web console (required on Fedora/RHEL)
systemctl enable console-getty.service &>/dev/null || true
@@ -879,7 +879,7 @@ EOF
cat >/etc/systemd/system/container-getty@1.service.d/override.conf <<'EOF'
[Service]
ExecStart=
-ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 $TERM
+ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 - $TERM
EOF
fi
@@ -898,10 +898,32 @@ EOF
;;
sysvinit)
- # Devuan/older systems - just modify inittab, no telinit needed during install
+ # Devuan/older systems - modify inittab for auto-login
+ # Devuan 5 (daedalus) uses SysVinit with various inittab formats
+ # CRITICAL: LXC uses /dev/console, NOT tty1! pct console connects to console device
if [[ -f /etc/inittab ]]; then
- sed -i 's|^1:2345:respawn:/sbin/getty.*|1:2345:respawn:/sbin/agetty --autologin root tty1 38400 linux|' /etc/inittab
+ # Backup original inittab
+ cp /etc/inittab /etc/inittab.bak 2>/dev/null || true
+
+ # First, enable autologin on tty1 (for direct access)
+ sed -i 's|^1:[0-9]*:respawn:.*/\(a\?getty\).*|1:2345:respawn:/sbin/agetty --autologin root --noclear tty1 38400 linux|' /etc/inittab
+
+ # CRITICAL: Add console entry for LXC - this is what pct console uses!
+ # Check if there's already a console getty entry
+ if ! grep -qE '^[^#].*respawn.*console' /etc/inittab; then
+ # Add new console entry for LXC
+ echo "" >>/etc/inittab
+ echo "# LXC console autologin (added by community-scripts)" >>/etc/inittab
+ echo "co:2345:respawn:/sbin/agetty --autologin root --noclear console 115200,38400,9600 linux" >>/etc/inittab
+ else
+ # Enable autologin on existing console entry
+ sed -i 's|^[^#]*:[0-9]*:respawn:.*/\(a\?getty\).*console.*|co:2345:respawn:/sbin/agetty --autologin root --noclear console 115200,38400,9600 linux|' /etc/inittab
+ fi
+
+ # Force a reload of inittab - try multiple methods
+ telinit q &>/dev/null || init q &>/dev/null || kill -1 1 &>/dev/null || true
fi
+ touch /root/.hushlogin
;;
esac
diff --git a/misc/old_misc/alpine-install.func b/misc/old_misc/alpine-install.func
index ddea81ecc..90a0ff00b 100644
--- a/misc/old_misc/alpine-install.func
+++ b/misc/old_misc/alpine-install.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/misc/old_misc/api.func b/misc/old_misc/api.func
index d42f919fc..f4091d551 100644
--- a/misc/old_misc/api.func
+++ b/misc/old_misc/api.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
diff --git a/misc/old_misc/build.func b/misc/old_misc/build.func
index d895d3c8d..060c1eafb 100644
--- a/misc/old_misc/build.func
+++ b/misc/old_misc/build.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
diff --git a/misc/old_misc/core.func b/misc/old_misc/core.func
index 1faba7296..5328d2a10 100644
--- a/misc/old_misc/core.func
+++ b/misc/old_misc/core.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
# ------------------------------------------------------------------------------
diff --git a/misc/old_misc/create_lxc.sh b/misc/old_misc/create_lxc.sh
index 975311f6a..b13aca462 100644
--- a/misc/old_misc/create_lxc.sh
+++ b/misc/old_misc/create_lxc.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/misc/old_misc/install.func b/misc/old_misc/install.func
index bd51cde15..4c7309a25 100644
--- a/misc/old_misc/install.func
+++ b/misc/old_misc/install.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT
diff --git a/misc/tools.func b/misc/tools.func
index a122317f3..7e18d475d 100644
--- a/misc/tools.func
+++ b/misc/tools.func
@@ -184,7 +184,10 @@ install_packages_with_retry() {
local retry=0
while [[ $retry -le $max_retries ]]; do
- if $STD apt install -y "${packages[@]}" 2>/dev/null; then
+ if DEBIAN_FRONTEND=noninteractive $STD apt install -y \
+ -o Dpkg::Options::="--force-confdef" \
+ -o Dpkg::Options::="--force-confold" \
+ "${packages[@]}" 2>/dev/null; then
return 0
fi
@@ -211,7 +214,10 @@ upgrade_packages_with_retry() {
local retry=0
while [[ $retry -le $max_retries ]]; do
- if $STD apt install --only-upgrade -y "${packages[@]}" 2>/dev/null; then
+ if DEBIAN_FRONTEND=noninteractive $STD apt install --only-upgrade -y \
+ -o Dpkg::Options::="--force-confdef" \
+ -o Dpkg::Options::="--force-confold" \
+ "${packages[@]}" 2>/dev/null; then
return 0
fi
@@ -334,9 +340,14 @@ remove_old_tool_version() {
$STD apt purge -y nodejs npm >/dev/null 2>&1 || true
# Clean up npm global modules
if command -v npm >/dev/null 2>&1; then
- npm list -g 2>/dev/null | grep -oE '^ \S+' | awk '{print $1}' | while read -r module; do
+ npm list -g 2>/dev/null | grep -oE '^ \S+' | awk '{print $1}' 2>/dev/null | while read -r module; do
npm uninstall -g "$module" >/dev/null 2>&1 || true
- done
+ done || true
+ fi
+ # Remove tarball installation if exists
+ if [[ -d "/usr/local/lib/nodejs" ]]; then
+ rm -rf /usr/local/lib/nodejs
+ rm -f /usr/local/bin/node /usr/local/bin/npm /usr/local/bin/npx
fi
cleanup_legacy_install "nodejs"
cleanup_tool_keyrings "nodesource"
@@ -1167,7 +1178,7 @@ cleanup_orphaned_sources() {
# Extract Signed-By path from .sources file
local keyring_path
- keyring_path=$(grep -E '^Signed-By:' "$sources_file" 2>/dev/null | awk '{print $2}')
+ keyring_path=$(grep -E '^Signed-By:' "$sources_file" 2>/dev/null | awk '{print $2}' 2>/dev/null || true)
# If keyring doesn't exist, remove the .sources file
if [[ -n "$keyring_path" ]] && [[ ! -f "$keyring_path" ]]; then
@@ -1759,7 +1770,10 @@ function fetch_and_deploy_gh_release() {
if [[ "$mode" == "tarball" || "$mode" == "source" ]]; then
# GitHub API's tarball_url/zipball_url can return HTTP 300 Multiple Choices
# when a branch and tag share the same name. Use explicit refs/tags/ URL instead.
- local direct_tarball_url="https://github.com/$repo/archive/refs/tags/$tag_name.tar.gz"
+ # URL-encode special characters in tag names (@ and /)
+ local encoded_tag_name="${tag_name//@/%40}"
+ encoded_tag_name="${encoded_tag_name//\//%2F}"
+ local direct_tarball_url="https://github.com/$repo/archive/refs/tags/$encoded_tag_name.tar.gz"
filename="${app_lc}-${version}.tar.gz"
curl $download_timeout -fsSL -o "$tmpdir/$filename" "$direct_tarball_url" || {
@@ -2073,7 +2087,7 @@ function setup_adminer() {
return 1
}
local VERSION
- VERSION=$(dpkg -s adminer 2>/dev/null | grep '^Version:' | awk '{print $2}')
+ VERSION=$(dpkg -s adminer 2>/dev/null | grep '^Version:' | awk '{print $2}' 2>/dev/null || echo 'unknown')
cache_installed_version "adminer" "${VERSION:-unknown}"
msg_ok "Setup Adminer (Debian/Ubuntu)"
fi
@@ -2563,109 +2577,576 @@ function setup_gs() {
# Sets up Hardware Acceleration on debian or ubuntu.
#
# Description:
-# - Determites CPU/GPU/APU Vendor
-# - Installs the correct libraries and packages
-# - Sets up Hardware Acceleration
+# - Detects all available GPUs (Intel, AMD, NVIDIA)
+# - Allows user to select which GPU(s) to configure (with 60s timeout)
+# - Installs the correct libraries and packages for each GPU type
+# - Supports: Debian 11/12/13, Ubuntu 22.04/24.04
+# - Intel: Legacy (Gen 6-8), Modern (Gen 9+), Arc
+# - AMD: Discrete GPUs, APUs, ROCm compute
+# - NVIDIA: Version-matched drivers from CUDA repository
#
# Notes:
-# - Some things are fetched from intel repositories due to not being in debian repositories.
+# - Some Intel packages are fetched from GitHub due to missing Debian packages
+# - NVIDIA requires matching host driver version
# ------------------------------------------------------------------------------
function setup_hwaccel() {
- msg_info "Setup Hardware Acceleration"
-
- if ! command -v lspci &>/dev/null; then
- $STD apt -y update || {
- msg_error "Failed to update package list"
- return 1
- }
- $STD apt -y install pciutils || {
- msg_error "Failed to install pciutils"
- return 1
- }
- fi
-
- # Detect GPU vendor (Intel, AMD, NVIDIA)
- local gpu_vendor gpu_info
- gpu_info=$(lspci 2>/dev/null | grep -Ei 'vga|3d|display' || echo "")
- gpu_vendor=$(echo "$gpu_info" | grep -Eo 'Intel|AMD|NVIDIA' | head -n1 || echo "")
-
- # Detect CPU vendor (relevant for AMD APUs)
- local cpu_vendor
- cpu_vendor=$(lscpu 2>/dev/null | grep -i 'Vendor ID' | awk '{print $3}' || echo "")
-
- if [[ -z "$gpu_vendor" && -z "$cpu_vendor" ]]; then
- msg_warn "No GPU or CPU vendor detected - skipping hardware acceleration setup"
- msg_ok "Setup Hardware Acceleration (skipped - no GPU detected)"
+ # Check if user explicitly disabled GPU in advanced settings
+ # ENABLE_GPU is exported from build.func
+ if [[ "${ENABLE_GPU:-no}" == "no" ]]; then
return 0
fi
- # Detect OS with fallbacks
+ # Check if GPU passthrough is enabled (device nodes must exist)
+ if [[ ! -d /dev/dri && ! -e /dev/nvidia0 && ! -e /dev/kfd ]]; then
+ msg_warn "No GPU passthrough detected (/dev/dri, /dev/nvidia*, /dev/kfd not found) - skipping hardware acceleration setup"
+ return 0
+ fi
+
+ msg_info "Setup Hardware Acceleration"
+
+ # Install pciutils if needed
+ if ! command -v lspci &>/dev/null; then
+ $STD apt -y update || {
+ msg_warn "Failed to update package list"
+ return 0
+ }
+ $STD apt -y install pciutils || {
+ msg_warn "Failed to install pciutils"
+ return 0
+ }
+ fi
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # GPU Detection - Build list of all available GPUs with details
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ local -a GPU_LIST=()
+ local -a GPU_TYPES=()
+ local -a GPU_NAMES=()
+ local gpu_count=0
+
+ # Get all GPU entries from lspci
+ while IFS= read -r line; do
+ [[ -z "$line" ]] && continue
+ local pci_addr gpu_name gpu_type=""
+
+ pci_addr=$(echo "$line" | awk '{print $1}')
+ gpu_name=$(echo "$line" | sed 's/^[^ ]* [^:]*: //')
+
+ # Determine GPU type
+ # Note: Use -w (word boundary) for ATI to avoid matching "CorporATIon"
+ if echo "$gpu_name" | grep -qi 'Intel'; then
+ gpu_type="INTEL"
+ # Subtype detection for Intel
+ # Order matters: Check Arc first, then Gen9+ (UHD/Iris/HD 5xx-6xx), then Legacy (HD 2xxx-5xxx)
+ # HD Graphics 530/630 = Gen 9 (Skylake/Kaby Lake) - 3 digits
+ # HD Graphics 4600/5500 = Gen 7-8 (Haswell/Broadwell) - 4 digits starting with 2-5
+ if echo "$gpu_name" | grep -qiE 'Arc|DG[12]'; then
+ gpu_type="INTEL_ARC"
+ elif echo "$gpu_name" | grep -qiE 'UHD|Iris|HD Graphics [5-6][0-9]{2}[^0-9]|HD Graphics [5-6][0-9]{2}$'; then
+ # HD Graphics 5xx/6xx (3 digits) = Gen 9+ (Skylake onwards)
+ gpu_type="INTEL_GEN9+"
+ elif echo "$gpu_name" | grep -qiE 'HD Graphics [2-5][0-9]{3}'; then
+ # HD Graphics 2xxx-5xxx (4 digits) = Gen 6-8 Legacy
+ gpu_type="INTEL_LEGACY"
+ fi
+ elif echo "$gpu_name" | grep -qiwE 'AMD|ATI|Radeon|Advanced Micro Devices'; then
+ gpu_type="AMD"
+ elif echo "$gpu_name" | grep -qi 'NVIDIA'; then
+ gpu_type="NVIDIA"
+ fi
+
+ if [[ -n "$gpu_type" ]]; then
+ GPU_LIST+=("$pci_addr")
+ GPU_TYPES+=("$gpu_type")
+ GPU_NAMES+=("$gpu_name")
+ ((gpu_count++)) || true
+ fi
+ done < <(lspci 2>/dev/null | grep -Ei 'vga|3d|display')
+
+ # Check for AMD APU via CPU vendor if no discrete GPU found
+ local cpu_vendor
+ cpu_vendor=$(lscpu 2>/dev/null | grep -i 'Vendor ID' | awk '{print $3}' 2>/dev/null || echo "")
+
+ if [[ $gpu_count -eq 0 ]]; then
+ if [[ "$cpu_vendor" == "AuthenticAMD" ]]; then
+ GPU_LIST+=("integrated")
+ GPU_TYPES+=("AMD_APU")
+ GPU_NAMES+=("AMD APU (Integrated Graphics)")
+ ((gpu_count++)) || true
+ else
+ msg_warn "No GPU detected - skipping hardware acceleration setup"
+ return 0
+ fi
+ fi
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # GPU Selection - Let user choose which GPU(s) to configure
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ local -a SELECTED_INDICES=()
+
+ if [[ $gpu_count -eq 1 ]]; then
+ # Single GPU - auto-select
+ SELECTED_INDICES=(0)
+ msg_ok "Detected GPU: ${GPU_NAMES[0]} (${GPU_TYPES[0]})"
+ else
+ # Multiple GPUs - show selection menu
+ echo ""
+ msg_info "Multiple GPUs detected:"
+ echo ""
+ for i in "${!GPU_LIST[@]}"; do
+ local type_display="${GPU_TYPES[$i]}"
+ case "${GPU_TYPES[$i]}" in
+ INTEL_ARC) type_display="Intel Arc" ;;
+ INTEL_GEN9+) type_display="Intel Gen9+" ;;
+ INTEL_LEGACY) type_display="Intel Legacy" ;;
+ INTEL) type_display="Intel" ;;
+ AMD) type_display="AMD" ;;
+ AMD_APU) type_display="AMD APU" ;;
+ NVIDIA) type_display="NVIDIA" ;;
+ esac
+ printf " %d) [%s] %s\n" "$((i + 1))" "$type_display" "${GPU_NAMES[$i]}"
+ done
+ printf " A) Configure ALL GPUs\n"
+ echo ""
+
+ # Read with 60 second timeout
+ local selection=""
+ echo -n "Select GPU(s) to configure (1-${gpu_count}, A=all) [timeout 60s, default=all]: "
+ if read -r -t 60 selection; then
+ selection="${selection^^}" # uppercase
+ else
+ echo ""
+ msg_info "Timeout - configuring all GPUs automatically"
+ selection="A"
+ fi
+
+ # Parse selection
+ if [[ "$selection" == "A" || -z "$selection" ]]; then
+ # Select all
+ for i in "${!GPU_LIST[@]}"; do
+ SELECTED_INDICES+=("$i")
+ done
+ elif [[ "$selection" =~ ^[0-9,]+$ ]]; then
+ # Parse comma-separated numbers
+ IFS=',' read -ra nums <<<"$selection"
+ for num in "${nums[@]}"; do
+ num=$(echo "$num" | tr -d ' ')
+ if [[ "$num" =~ ^[0-9]+$ ]] && ((num >= 1 && num <= gpu_count)); then
+ SELECTED_INDICES+=("$((num - 1))")
+ fi
+ done
+ else
+ # Invalid - default to all
+ msg_warn "Invalid selection - configuring all GPUs"
+ for i in "${!GPU_LIST[@]}"; do
+ SELECTED_INDICES+=("$i")
+ done
+ fi
+ fi
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # OS Detection
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
local os_id os_codename os_version
os_id=$(grep -oP '(?<=^ID=).+' /etc/os-release 2>/dev/null | tr -d '"' || echo "debian")
os_codename=$(grep -oP '(?<=^VERSION_CODENAME=).+' /etc/os-release 2>/dev/null | tr -d '"' || echo "unknown")
os_version=$(grep -oP '(?<=^VERSION_ID=).+' /etc/os-release 2>/dev/null | tr -d '"' || echo "")
-
[[ -z "$os_id" ]] && os_id="debian"
- # Determine if we are in a privileged LXC container
local in_ct="${CTTYPE:-0}"
- case "$gpu_vendor" in
- Intel)
- # Detect Intel GPU generation for driver selection
- # Gen 9+ (Skylake and newer) benefit from non-free drivers
- local intel_gen=""
- local needs_nonfree=false
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # Process Selected GPUs
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ for idx in "${SELECTED_INDICES[@]}"; do
+ local gpu_type="${GPU_TYPES[$idx]}"
+ local gpu_name="${GPU_NAMES[$idx]}"
- # Check for specific Intel GPU models that need non-free drivers
- if echo "$gpu_info" | grep -Ei 'HD Graphics [56][0-9]{2}|UHD Graphics|Iris|Arc|DG[12]' &>/dev/null; then
- needs_nonfree=true
- intel_gen="gen9+"
+ msg_info "Configuring: ${gpu_name}"
+
+ case "$gpu_type" in
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # Intel Arc GPUs (DG1, DG2, Arc A-series)
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ INTEL_ARC)
+ _setup_intel_arc "$os_id" "$os_codename"
+ ;;
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # Intel Gen 9+ (Skylake 2015+: UHD, Iris, HD 6xx+)
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ INTEL_GEN9+ | INTEL)
+ _setup_intel_modern "$os_id" "$os_codename"
+ ;;
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # Intel Legacy (Gen 6-8: HD 2000-5999, Sandy Bridge to Broadwell)
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ INTEL_LEGACY)
+ _setup_intel_legacy "$os_id" "$os_codename"
+ ;;
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # AMD Discrete GPUs
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ AMD)
+ _setup_amd_gpu "$os_id" "$os_codename"
+ ;;
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # AMD APU (Integrated Graphics)
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ AMD_APU)
+ _setup_amd_apu "$os_id" "$os_codename"
+ ;;
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # NVIDIA GPUs
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ NVIDIA)
+ _setup_nvidia_gpu "$os_id" "$os_codename" "$os_version"
+ ;;
+ esac
+ done
+
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ # Device Permissions
+ # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+ _setup_gpu_permissions "$in_ct"
+
+ cache_installed_version "hwaccel" "1.0"
+ msg_ok "Setup Hardware Acceleration"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Intel Arc GPU Setup
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_intel_arc() {
+ local os_id="$1" os_codename="$2"
+
+ msg_info "Installing Intel Arc GPU drivers"
+
+ if [[ "$os_id" == "ubuntu" ]]; then
+ # Ubuntu 22.04+ has Arc support in HWE kernel
+ $STD apt -y install \
+ intel-media-va-driver-non-free \
+ intel-opencl-icd \
+ vainfo \
+ intel-gpu-tools 2>/dev/null || msg_warn "Some Intel Arc packages failed"
+
+ elif [[ "$os_id" == "debian" ]]; then
+ # Add non-free repos
+ _add_debian_nonfree "$os_codename"
+
+ # Arc requires latest drivers - fetch from GitHub
+ # Order matters: libigdgmm first (dependency), then IGC, then compute-runtime
+ msg_info "Fetching Intel compute-runtime for Arc support"
+
+ # libigdgmm - bundled in compute-runtime releases (Debian version often too old)
+ fetch_and_deploy_gh_release "libigdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || true
+
+ # Intel Graphics Compiler (note: packages have -2 suffix)
+ fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || true
+ fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || true
+
+ # Compute Runtime (depends on IGC and gmmlib)
+ fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || true
+ fetch_and_deploy_gh_release "intel-level-zero-gpu" "intel/compute-runtime" "binary" "latest" "" "libze-intel-gpu1_*_amd64.deb" || true
+
+ $STD apt -y install \
+ intel-media-va-driver-non-free \
+ ocl-icd-libopencl1 \
+ libvpl2 \
+ vainfo \
+ intel-gpu-tools 2>/dev/null || msg_warn "Some Intel Arc packages failed"
+ fi
+
+ msg_ok "Intel Arc GPU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Intel Modern GPU Setup (Gen 9+)
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_intel_modern() {
+ local os_id="$1" os_codename="$2"
+
+ msg_info "Installing Intel Gen 9+ GPU drivers"
+
+ if [[ "$os_id" == "ubuntu" ]]; then
+ $STD apt -y install \
+ va-driver-all \
+ intel-media-va-driver \
+ ocl-icd-libopencl1 \
+ vainfo \
+ intel-gpu-tools 2>/dev/null || msg_warn "Some Intel packages failed"
+
+ # Try non-free driver for better codec support
+ $STD apt -y install intel-media-va-driver-non-free 2>/dev/null || true
+ $STD apt -y install intel-opencl-icd 2>/dev/null || true
+ $STD apt -y install libmfx-gen1.2 2>/dev/null || true
+
+ elif [[ "$os_id" == "debian" ]]; then
+ _add_debian_nonfree "$os_codename"
+
+ # For Trixie/Sid: Fetch from GitHub (Debian packages too old or missing)
+ if [[ "$os_codename" == "trixie" || "$os_codename" == "sid" ]]; then
+ msg_info "Fetching Intel compute-runtime from GitHub"
+
+ # libigdgmm first (bundled in compute-runtime releases)
+ fetch_and_deploy_gh_release "libigdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || true
+
+ # Intel Graphics Compiler (note: packages have -2 suffix)
+ fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || true
+ fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || true
+
+ # Compute Runtime
+ fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || true
fi
- if [[ "$os_id" == "ubuntu" ]]; then
- # Ubuntu: Use packages from Ubuntu repos
- $STD apt -y install \
- va-driver-all \
- ocl-icd-libopencl1 \
- intel-opencl-icd \
- vainfo \
- intel-gpu-tools || {
- msg_error "Failed to install Intel GPU dependencies"
- return 1
- }
- # Try to install intel-media-va-driver for newer GPUs
- $STD apt -y install intel-media-va-driver 2>/dev/null || true
+ $STD apt -y install \
+ intel-media-va-driver-non-free \
+ ocl-icd-libopencl1 \
+ vainfo \
+ libmfx-gen1.2 \
+ intel-gpu-tools 2>/dev/null || msg_warn "Some Intel packages failed"
- elif [[ "$os_id" == "debian" ]]; then
- # Debian: Check version and install appropriate drivers
- if [[ "$needs_nonfree" == true ]]; then
- # Add non-free repo for intel-media-va-driver-non-free
- if [[ "$os_codename" == "bookworm" ]]; then
- # Debian 12 Bookworm
- if [[ ! -f /etc/apt/sources.list.d/non-free.list && ! -f /etc/apt/sources.list.d/non-free.sources ]]; then
- cat </etc/apt/sources.list.d/non-free.sources
+ # Bookworm has intel-opencl-icd in repos (compatible version)
+ [[ "$os_codename" == "bookworm" ]] && $STD apt -y install intel-opencl-icd libigdgmm12 2>/dev/null || true
+ fi
+
+ msg_ok "Intel Gen 9+ GPU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Intel Legacy GPU Setup (Gen 6-8)
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_intel_legacy() {
+ local os_id="$1" os_codename="$2"
+
+ msg_info "Installing Intel Legacy GPU drivers (Gen 6-8)"
+
+ # Legacy GPUs use i965 driver - stable repo packages only
+ $STD apt -y install \
+ va-driver-all \
+ i965-va-driver \
+ mesa-va-drivers \
+ ocl-icd-libopencl1 \
+ vainfo \
+ intel-gpu-tools 2>/dev/null || msg_warn "Some Intel legacy packages failed"
+
+ # beignet provides OpenCL for older Intel GPUs (Sandy Bridge to Broadwell)
+ # Note: beignet-opencl-icd was removed in Debian 12+ and Ubuntu 22.04+
+ # Check if package is available before attempting installation
+ if apt-cache show beignet-opencl-icd &>/dev/null; then
+ $STD apt -y install beignet-opencl-icd 2>/dev/null || msg_warn "beignet-opencl-icd installation failed (optional)"
+ else
+ msg_warn "beignet-opencl-icd not available - OpenCL support for legacy Intel GPU limited"
+ msg_warn "Note: Hardware video encoding/decoding (VA-API) still works without OpenCL"
+ fi
+
+ msg_ok "Intel Legacy GPU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# AMD Discrete GPU Setup
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_amd_gpu() {
+ local os_id="$1" os_codename="$2"
+
+ msg_info "Installing AMD GPU drivers"
+
+ # Core Mesa drivers
+ $STD apt -y install \
+ mesa-va-drivers \
+ mesa-vdpau-drivers \
+ mesa-opencl-icd \
+ ocl-icd-libopencl1 \
+ libdrm-amdgpu1 \
+ vainfo \
+ clinfo 2>/dev/null || msg_warn "Some AMD packages failed"
+
+ # Firmware for AMD GPUs
+ if [[ "$os_id" == "debian" ]]; then
+ _add_debian_nonfree_firmware "$os_codename"
+ $STD apt -y install firmware-amd-graphics 2>/dev/null || msg_warn "AMD firmware not available"
+ fi
+ # Ubuntu includes AMD firmware in linux-firmware by default
+
+ # ROCm for compute (optional - large download)
+ # Uncomment if needed:
+ # $STD apt -y install rocm-opencl-runtime 2>/dev/null || true
+
+ msg_ok "AMD GPU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# AMD APU Setup (Integrated Graphics)
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_amd_apu() {
+ local os_id="$1" os_codename="$2"
+
+ msg_info "Installing AMD APU drivers"
+
+ $STD apt -y install \
+ mesa-va-drivers \
+ mesa-vdpau-drivers \
+ mesa-opencl-icd \
+ ocl-icd-libopencl1 \
+ vainfo 2>/dev/null || msg_warn "Some AMD APU packages failed"
+
+ if [[ "$os_id" == "debian" ]]; then
+ _add_debian_nonfree_firmware "$os_codename"
+ $STD apt -y install firmware-amd-graphics 2>/dev/null || true
+ fi
+
+ msg_ok "AMD APU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# NVIDIA GPU Setup
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_nvidia_gpu() {
+ local os_id="$1" os_codename="$2" os_version="$3"
+
+ msg_info "Installing NVIDIA GPU drivers"
+
+ # Detect host driver version (passed through via /proc)
+ local nvidia_host_version=""
+ if [[ -f /proc/driver/nvidia/version ]]; then
+ nvidia_host_version=$(grep "NVRM version:" /proc/driver/nvidia/version 2>/dev/null | awk '{print $8}')
+ fi
+
+ if [[ -z "$nvidia_host_version" ]]; then
+ msg_warn "NVIDIA host driver version not found in /proc/driver/nvidia/version"
+ msg_warn "Ensure NVIDIA drivers are installed on host and GPU passthrough is enabled"
+ $STD apt -y install va-driver-all vainfo 2>/dev/null || true
+ return 0
+ fi
+
+ msg_info "Host NVIDIA driver version: ${nvidia_host_version}"
+
+ if [[ "$os_id" == "debian" ]]; then
+ # Enable non-free components
+ if [[ -f /etc/apt/sources.list.d/debian.sources ]]; then
+ if ! grep -q "non-free" /etc/apt/sources.list.d/debian.sources 2>/dev/null; then
+ sed -i -E 's/Components: (.*)$/Components: \1 contrib non-free non-free-firmware/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || true
+ fi
+ fi
+
+ # Determine CUDA repository
+ local cuda_repo="debian12"
+ case "$os_codename" in
+ bullseye) cuda_repo="debian11" ;;
+ bookworm) cuda_repo="debian12" ;;
+ trixie | sid) cuda_repo="debian12" ;; # Forward compatible
+ esac
+
+ # Add NVIDIA CUDA repository
+ if [[ ! -f /usr/share/keyrings/cuda-archive-keyring.gpg ]]; then
+ msg_info "Adding NVIDIA CUDA repository (${cuda_repo})"
+ local cuda_keyring
+ cuda_keyring="$(mktemp)"
+ if curl -fsSL -o "$cuda_keyring" "https://developer.download.nvidia.com/compute/cuda/repos/${cuda_repo}/x86_64/cuda-keyring_1.1-1_all.deb" 2>/dev/null; then
+ $STD dpkg -i "$cuda_keyring" 2>/dev/null || true
+ else
+ msg_warn "Failed to download NVIDIA CUDA keyring"
+ fi
+ rm -f "$cuda_keyring"
+ fi
+
+ # Pin NVIDIA repo for version matching
+ cat <<'NVIDIA_PIN' >/etc/apt/preferences.d/nvidia-cuda-pin
+Package: *
+Pin: origin developer.download.nvidia.com
+Pin-Priority: 1001
+NVIDIA_PIN
+
+ $STD apt -y update
+
+ # Install version-matched NVIDIA libraries
+ local nvidia_pkgs="libcuda1=${nvidia_host_version}* libnvcuvid1=${nvidia_host_version}* libnvidia-encode1=${nvidia_host_version}* libnvidia-ml1=${nvidia_host_version}*"
+
+ msg_info "Installing NVIDIA libraries (version ${nvidia_host_version})"
+ if $STD apt -y install --no-install-recommends $nvidia_pkgs 2>/dev/null; then
+ msg_ok "Installed version-matched NVIDIA libraries"
+ else
+ msg_warn "Version-pinned install failed - trying unpinned"
+ if $STD apt -y install --no-install-recommends libcuda1 libnvcuvid1 libnvidia-encode1 libnvidia-ml1 2>/dev/null; then
+ msg_warn "Installed NVIDIA libraries (unpinned) - version mismatch may occur"
+ else
+ msg_warn "NVIDIA library installation failed"
+ fi
+ fi
+
+ $STD apt -y install --no-install-recommends nvidia-smi 2>/dev/null || true
+
+ elif [[ "$os_id" == "ubuntu" ]]; then
+ # Ubuntu versioning
+ local ubuntu_cuda_repo=""
+ case "$os_version" in
+ 22.04) ubuntu_cuda_repo="ubuntu2204" ;;
+ 24.04) ubuntu_cuda_repo="ubuntu2404" ;;
+ *) ubuntu_cuda_repo="ubuntu2204" ;; # Fallback
+ esac
+
+ # Add NVIDIA CUDA repository for Ubuntu
+ if [[ ! -f /usr/share/keyrings/cuda-archive-keyring.gpg ]]; then
+ msg_info "Adding NVIDIA CUDA repository (${ubuntu_cuda_repo})"
+ local cuda_keyring
+ cuda_keyring="$(mktemp)"
+ if curl -fsSL -o "$cuda_keyring" "https://developer.download.nvidia.com/compute/cuda/repos/${ubuntu_cuda_repo}/x86_64/cuda-keyring_1.1-1_all.deb" 2>/dev/null; then
+ $STD dpkg -i "$cuda_keyring" 2>/dev/null || true
+ else
+ msg_warn "Failed to download NVIDIA CUDA keyring"
+ fi
+ rm -f "$cuda_keyring"
+ fi
+
+ $STD apt -y update
+
+ # Try version-matched install
+ local nvidia_pkgs="libcuda1=${nvidia_host_version}* libnvcuvid1=${nvidia_host_version}* libnvidia-encode1=${nvidia_host_version}* libnvidia-ml1=${nvidia_host_version}*"
+ if $STD apt -y install --no-install-recommends $nvidia_pkgs 2>/dev/null; then
+ msg_ok "Installed version-matched NVIDIA libraries"
+ else
+ # Fallback to Ubuntu repo packages
+ $STD apt -y install --no-install-recommends libnvidia-decode libnvidia-encode nvidia-utils 2>/dev/null || msg_warn "NVIDIA installation failed"
+ fi
+ fi
+
+ # VA-API for hybrid setups (Intel + NVIDIA)
+ $STD apt -y install va-driver-all vainfo 2>/dev/null || true
+
+ msg_ok "NVIDIA GPU configured"
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Helper: Add Debian non-free repositories
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_add_debian_nonfree() {
+ local os_codename="$1"
+
+ [[ -f /etc/apt/sources.list.d/non-free.sources ]] && return 0
+
+ case "$os_codename" in
+ bullseye)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free.sources
+Types: deb
+URIs: http://deb.debian.org/debian
+Suites: bullseye bullseye-updates
+Components: non-free
+EOF
+ ;;
+ bookworm)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free.sources
Types: deb
URIs: http://deb.debian.org/debian
Suites: bookworm bookworm-updates
Components: non-free non-free-firmware
EOF
- $STD apt update
- fi
- $STD apt -y install \
- intel-media-va-driver-non-free \
- ocl-icd-libopencl1 \
- intel-opencl-icd \
- vainfo \
- intel-gpu-tools || {
- msg_warn "Non-free driver install failed, falling back to open drivers"
- needs_nonfree=false
- }
-
- elif [[ "$os_codename" == "trixie" || "$os_codename" == "sid" ]]; then
- # Debian 13 Trixie / Sid
- if [[ ! -f /etc/apt/sources.list.d/non-free.sources ]]; then
- cat <<'EOF' >/etc/apt/sources.list.d/non-free.sources
+ ;;
+ trixie | sid)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free.sources
Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
@@ -2676,113 +3157,135 @@ URIs: http://deb.debian.org/debian-security
Suites: trixie-security
Components: non-free non-free-firmware
EOF
- $STD apt update
- fi
- $STD apt -y install \
- intel-media-va-driver-non-free \
- ocl-icd-libopencl1 \
- mesa-opencl-icd \
- mesa-va-drivers \
- libvpl2 \
- vainfo \
- intel-gpu-tools 2>/dev/null || {
- msg_warn "Non-free driver install failed, falling back to open drivers"
- needs_nonfree=false
- }
- fi
- fi
-
- # Fallback to open drivers or older Intel GPUs
- if [[ "$needs_nonfree" == false ]]; then
- # Fetch latest Intel drivers from GitHub for Debian
- fetch_and_deploy_gh_release "" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || {
- msg_warn "Failed to deploy Intel IGC core 2"
- }
- fetch_and_deploy_gh_release "" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || {
- msg_warn "Failed to deploy Intel IGC OpenCL 2"
- }
- fetch_and_deploy_gh_release "" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || {
- msg_warn "Failed to deploy Intel GDGMM12"
- }
- fetch_and_deploy_gh_release "" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || {
- msg_warn "Failed to deploy Intel OpenCL ICD"
- }
-
- $STD apt -y install \
- va-driver-all \
- ocl-icd-libopencl1 \
- mesa-opencl-icd \
- mesa-va-drivers \
- vainfo \
- intel-gpu-tools || {
- msg_error "Failed to install Intel GPU dependencies"
- return 1
- }
- fi
- fi
- ;;
-
- AMD)
- $STD apt -y install \
- mesa-va-drivers \
- mesa-vdpau-drivers \
- mesa-opencl-icd \
- ocl-icd-libopencl1 \
- vainfo \
- clinfo 2>/dev/null || {
- msg_error "Failed to install AMD GPU dependencies"
- return 1
- }
-
- # AMD firmware for better GPU support
- if [[ "$os_id" == "debian" ]]; then
- $STD apt -y install firmware-amd-graphics 2>/dev/null || true
- fi
- $STD apt -y install libdrm-amdgpu1 2>/dev/null || true
- ;;
-
- NVIDIA)
- # NVIDIA needs manual driver setup or passthrough from host
- msg_warn "NVIDIA GPU detected - driver must be installed manually or passed through from host"
- # Install basic VA-API support for potential hybrid setups
- $STD apt -y install va-driver-all vainfo 2>/dev/null || true
- ;;
-
- *)
- # No discrete GPU detected - check for AMD APU
- if [[ "$cpu_vendor" == "AuthenticAMD" ]]; then
- $STD apt -y install \
- mesa-va-drivers \
- mesa-vdpau-drivers \
- mesa-opencl-icd \
- ocl-icd-libopencl1 \
- vainfo 2>/dev/null || true
- else
- msg_warn "No supported GPU vendor detected - skipping GPU driver installation"
- fi
;;
esac
+ $STD apt -y update
+}
- # Set permissions for /dev/dri (only in privileged containers and if /dev/dri exists)
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Helper: Add Debian non-free-firmware repository
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_add_debian_nonfree_firmware() {
+ local os_codename="$1"
+
+ [[ -f /etc/apt/sources.list.d/non-free-firmware.sources ]] && return 0
+
+ case "$os_codename" in
+ bullseye)
+ # Debian 11 uses 'non-free' component (no separate non-free-firmware)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free-firmware.sources
+Types: deb
+URIs: http://deb.debian.org/debian
+Suites: bullseye bullseye-updates
+Components: non-free
+
+Types: deb
+URIs: http://deb.debian.org/debian-security
+Suites: bullseye-security
+Components: non-free
+EOF
+ ;;
+ bookworm)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free-firmware.sources
+Types: deb
+URIs: http://deb.debian.org/debian
+Suites: bookworm bookworm-updates
+Components: non-free-firmware
+
+Types: deb
+URIs: http://deb.debian.org/debian-security
+Suites: bookworm-security
+Components: non-free-firmware
+EOF
+ ;;
+ trixie | sid)
+ cat <<'EOF' >/etc/apt/sources.list.d/non-free-firmware.sources
+Types: deb
+URIs: http://deb.debian.org/debian
+Suites: trixie trixie-updates
+Components: non-free-firmware
+
+Types: deb
+URIs: http://deb.debian.org/debian-security
+Suites: trixie-security
+Components: non-free-firmware
+EOF
+ ;;
+ esac
+ $STD apt -y update
+}
+
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+# Helper: Setup GPU device permissions
+# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+_setup_gpu_permissions() {
+ local in_ct="$1"
+
+ # /dev/dri permissions (Intel/AMD)
if [[ "$in_ct" == "0" && -d /dev/dri ]]; then
- chgrp video /dev/dri 2>/dev/null || true
- chmod 755 /dev/dri 2>/dev/null || true
- chmod 660 /dev/dri/* 2>/dev/null || true
- $STD adduser "$(id -u -n)" video 2>/dev/null || true
- $STD adduser "$(id -u -n)" render 2>/dev/null || true
+ if ls /dev/dri/card* /dev/dri/renderD* &>/dev/null; then
+ chgrp video /dev/dri 2>/dev/null || true
+ chmod 755 /dev/dri 2>/dev/null || true
+ chmod 660 /dev/dri/* 2>/dev/null || true
+ $STD adduser "$(id -u -n)" video 2>/dev/null || true
+ $STD adduser "$(id -u -n)" render 2>/dev/null || true
- # Sync GID for video/render groups between host and container
- local host_video_gid host_render_gid
- host_video_gid=$(getent group video | cut -d: -f3)
- host_render_gid=$(getent group render | cut -d: -f3)
- if [[ -n "$host_video_gid" && -n "$host_render_gid" ]]; then
- sed -i "s/^video:x:[0-9]*:/video:x:$host_video_gid:/" /etc/group 2>/dev/null || true
- sed -i "s/^render:x:[0-9]*:/render:x:$host_render_gid:/" /etc/group 2>/dev/null || true
+ # Sync GID with host
+ local host_video_gid host_render_gid
+ host_video_gid=$(getent group video | cut -d: -f3)
+ host_render_gid=$(getent group render | cut -d: -f3)
+ if [[ -n "$host_video_gid" ]]; then
+ sed -i "s/^video:x:[0-9]*:/video:x:$host_video_gid:/" /etc/group 2>/dev/null || true
+ fi
+ if [[ -n "$host_render_gid" ]]; then
+ sed -i "s/^render:x:[0-9]*:/render:x:$host_render_gid:/" /etc/group 2>/dev/null || true
+ fi
+
+ # Verify VA-API
+ if command -v vainfo &>/dev/null; then
+ if vainfo &>/dev/null; then
+ msg_info "VA-API verified and working"
+ else
+ msg_warn "vainfo test failed - check GPU passthrough"
+ fi
+ fi
fi
fi
- cache_installed_version "hwaccel" "1.0"
- msg_ok "Setup Hardware Acceleration"
+ # /dev/nvidia* permissions (NVIDIA)
+ if ls /dev/nvidia* &>/dev/null 2>&1; then
+ msg_info "Configuring NVIDIA device permissions"
+ for nvidia_dev in /dev/nvidia*; do
+ [[ -e "$nvidia_dev" ]] && {
+ chgrp video "$nvidia_dev" 2>/dev/null || true
+ chmod 666 "$nvidia_dev" 2>/dev/null || true
+ }
+ done
+ if [[ -d /dev/nvidia-caps ]]; then
+ chmod 755 /dev/nvidia-caps 2>/dev/null || true
+ for caps_dev in /dev/nvidia-caps/*; do
+ [[ -e "$caps_dev" ]] && {
+ chgrp video "$caps_dev" 2>/dev/null || true
+ chmod 666 "$caps_dev" 2>/dev/null || true
+ }
+ done
+ fi
+
+ # Verify nvidia-smi
+ if command -v nvidia-smi &>/dev/null; then
+ if nvidia-smi &>/dev/null; then
+ msg_info "nvidia-smi verified and working"
+ else
+ msg_warn "nvidia-smi test failed - check driver version match"
+ fi
+ fi
+ fi
+
+ # /dev/kfd permissions (AMD ROCm)
+ if [[ -e /dev/kfd ]]; then
+ chmod 666 /dev/kfd 2>/dev/null || true
+ msg_info "AMD ROCm compute device configured"
+ fi
}
# ------------------------------------------------------------------------------
@@ -3081,6 +3584,11 @@ EOF
setup_mariadb() {
local MARIADB_VERSION="${MARIADB_VERSION:-latest}"
+ # Ensure non-interactive mode for all apt operations
+ export DEBIAN_FRONTEND=noninteractive
+ export NEEDRESTART_MODE=a
+ export NEEDRESTART_SUSPEND=1
+
# Resolve "latest" to actual version
if [[ "$MARIADB_VERSION" == "latest" ]]; then
if ! curl -fsI --max-time 10 http://mirror.mariadb.org/repo/ >/dev/null 2>&1; then
@@ -3119,6 +3627,20 @@ setup_mariadb() {
local CURRENT_VERSION=""
CURRENT_VERSION=$(is_tool_installed "mariadb" 2>/dev/null) || true
+ # Pre-configure debconf to prevent any interactive prompts during install/upgrade
+ local MARIADB_MAJOR_MINOR
+ MARIADB_MAJOR_MINOR=$(echo "$MARIADB_VERSION" | awk -F. '{print $1"."$2}')
+ if [[ -n "$MARIADB_MAJOR_MINOR" ]]; then
+ debconf-set-selections </etc/tmpfiles.d/mariadb.conf; then
+ msg_warn "Failed to create /etc/tmpfiles.d/mariadb.conf - runtime directory may not persist on reboot"
+ fi
+
+ # Create the directory now if it doesn't exist
+ # Verify mysql user exists before attempting ownership change
+ if [[ ! -d /run/mysqld ]]; then
+ mkdir -p /run/mysqld
+ # Set permissions first (works regardless of user existence)
+ chmod 755 /run/mysqld
+ # Set ownership only if mysql user exists
+ if getent passwd mysql >/dev/null 2>&1; then
+ chown mysql:mysql /run/mysqld
+ else
+ msg_warn "mysql user not found - directory created with correct permissions but ownership not set"
+ fi
+ fi
+
+ msg_ok "Configured MariaDB runtime directory persistence"
+
cache_installed_version "mariadb" "$MARIADB_VERSION"
msg_ok "Setup MariaDB $MARIADB_VERSION"
}
@@ -3308,6 +3847,11 @@ function setup_mongodb() {
DISTRO_ID=$(get_os_info id)
DISTRO_CODENAME=$(get_os_info codename)
+ # Ensure non-interactive mode for all apt operations
+ export DEBIAN_FRONTEND=noninteractive
+ export NEEDRESTART_MODE=a
+ export NEEDRESTART_SUSPEND=1
+
# Check AVX support
if ! grep -qm1 'avx[^ ]*' /proc/cpuinfo; then
local major="${MONGO_VERSION%%.*}"
@@ -3426,6 +3970,11 @@ function setup_mysql() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
+ # Ensure non-interactive mode for all apt operations
+ export DEBIAN_FRONTEND=noninteractive
+ export NEEDRESTART_MODE=a
+ export NEEDRESTART_SUSPEND=1
+
# Get currently installed version
local CURRENT_VERSION=""
CURRENT_VERSION=$(is_tool_installed "mysql" 2>/dev/null) || true
@@ -3520,7 +4069,6 @@ EOF
ensure_apt_working || return 1
# Try multiple package names with retry logic
- export DEBIAN_FRONTEND=noninteractive
local mysql_install_success=false
if apt-cache search "^mysql-server$" 2>/dev/null | grep -q . &&
@@ -3552,21 +4100,128 @@ EOF
msg_ok "Setup MySQL $MYSQL_VERSION"
}
+# ------------------------------------------------------------------------------
+# Installs Node.js from official prebuilt binaries (alternative to NodeSource repo).
+#
+# Description:
+# - Downloads official Node.js prebuilt binaries from nodejs.org
+# - Extracts to /usr/local and creates symlinks
+# - No package manager dependencies, no GPG issues
+#
+# Arguments:
+# $1 - Node.js major version (e.g. 22, 24)
+#
+# Returns:
+# 0 on success, 1 on failure
+# ------------------------------------------------------------------------------
+
+function install_nodejs_from_binary() {
+ local NODE_VERSION="$1"
+ local ARCH
+
+ # Determine system architecture
+ ARCH=$(dpkg --print-architecture 2>/dev/null || uname -m)
+ case "$ARCH" in
+ amd64 | x86_64) ARCH="x64" ;;
+ arm64 | aarch64) ARCH="arm64" ;;
+ armv7l | armhf) ARCH="armv7l" ;;
+ ppc64le) ARCH="ppc64le" ;;
+ s390x) ARCH="s390x" ;;
+ *)
+ msg_error "Unsupported architecture: $ARCH"
+ return 1
+ ;;
+ esac
+
+ msg_info "Fetching Node.js v${NODE_VERSION}.x binary metadata"
+
+ # Fetch latest version info from nodejs.org
+ local LATEST_URL="https://nodejs.org/dist/latest-v${NODE_VERSION}.x/"
+ local VERSION_INFO
+ VERSION_INFO=$(curl -fsSL "$LATEST_URL" 2>/dev/null | grep -oP "node-v${NODE_VERSION}\.[0-9]+\.[0-9]+-linux-${ARCH}\.tar\.xz" | head -n1)
+
+ if [[ -z "$VERSION_INFO" ]]; then
+ msg_error "Could not find Node.js v${NODE_VERSION}.x binary for linux-${ARCH}"
+ return 1
+ fi
+
+ local FULL_VERSION
+ FULL_VERSION=$(echo "$VERSION_INFO" | grep -oP "v${NODE_VERSION}\.[0-9]+\.[0-9]+")
+ local TARBALL_NAME="node-${FULL_VERSION}-linux-${ARCH}.tar.xz"
+ local TARBALL_URL="${LATEST_URL}${TARBALL_NAME}"
+ local CHECKSUM_URL="${LATEST_URL}SHASUMS256.txt"
+
+ msg_info "Downloading Node.js ${FULL_VERSION} for linux-${ARCH}"
+
+ # Download tarball and checksum
+ local TEMP_DIR
+ TEMP_DIR=$(mktemp -d)
+ trap "rm -rf '$TEMP_DIR'" EXIT
+
+ if ! curl -fsSL -o "${TEMP_DIR}/${TARBALL_NAME}" "$TARBALL_URL"; then
+ msg_error "Failed to download Node.js binary from $TARBALL_URL"
+ return 1
+ fi
+
+ if ! curl -fsSL -o "${TEMP_DIR}/SHASUMS256.txt" "$CHECKSUM_URL"; then
+ msg_warn "Could not download checksum file - skipping verification"
+ else
+ # Verify checksum
+ msg_info "Verifying checksum"
+ cd "$TEMP_DIR" || return 1
+ if ! grep "$TARBALL_NAME" SHASUMS256.txt | sha256sum -c - >/dev/null 2>&1; then
+ msg_error "Checksum verification failed for $TARBALL_NAME"
+ return 1
+ fi
+ msg_ok "Checksum verified"
+ fi
+
+ # Remove old Node.js installation if exists
+ if [[ -d "/usr/local/lib/nodejs" ]]; then
+ msg_info "Removing old Node.js installation"
+ rm -rf /usr/local/lib/nodejs
+ fi
+
+ # Extract tarball
+ msg_info "Installing Node.js ${FULL_VERSION}"
+ mkdir -p /usr/local/lib/nodejs
+ tar -xJf "${TEMP_DIR}/${TARBALL_NAME}" -C /usr/local/lib/nodejs --strip-components=1
+
+ # Create symlinks
+ ln -sf /usr/local/lib/nodejs/bin/node /usr/local/bin/node
+ ln -sf /usr/local/lib/nodejs/bin/npm /usr/local/bin/npm
+ ln -sf /usr/local/lib/nodejs/bin/npx /usr/local/bin/npx
+
+ # Verify installation
+ if ! /usr/local/bin/node --version >/dev/null 2>&1; then
+ msg_error "Node.js installation verification failed"
+ return 1
+ fi
+
+ local INSTALLED_VERSION
+ INSTALLED_VERSION=$(/usr/local/bin/node --version 2>/dev/null)
+ msg_ok "Installed Node.js ${INSTALLED_VERSION}"
+
+ return 0
+}
+
# ------------------------------------------------------------------------------
# Installs Node.js and optional global modules.
#
# Description:
-# - Installs specified Node.js version using NodeSource APT repo
+# - Installs specified Node.js version using NodeSource APT repo OR official binaries
# - Optionally installs or updates global npm modules
#
# Variables:
-# NODE_VERSION - Node.js version to install (default: 24 LTS)
-# NODE_MODULE - Comma-separated list of global modules (e.g. "yarn,@vue/cli@5.0.0")
+# NODE_VERSION - Node.js version to install (default: 24 LTS)
+# NODE_MODULE - Comma-separated list of global modules (e.g. "yarn,@vue/cli@5.0.0")
+# NODE_INSTALL_METHOD - Installation method: "nodesource" (default) or "binary"
# ------------------------------------------------------------------------------
function setup_nodejs() {
local NODE_VERSION="${NODE_VERSION:-24}"
local NODE_MODULE="${NODE_MODULE:-}"
+ local NODE_INSTALL_METHOD="${NODE_INSTALL_METHOD:-nodesource}"
# ALWAYS clean up legacy installations first (nvm, etc.) to prevent conflicts
cleanup_legacy_install "nodejs"
@@ -3588,7 +4243,17 @@ function setup_nodejs() {
if [[ -n "$CURRENT_NODE_VERSION" && "$CURRENT_NODE_VERSION" == "$NODE_VERSION" ]]; then
msg_info "Update Node.js $NODE_VERSION"
- ensure_apt_working || return 1
+ # For binary method, check if there's a newer patch version available
+ if [[ "$NODE_INSTALL_METHOD" == "binary" ]]; then
+ local CURRENT_FULL_VERSION
+ CURRENT_FULL_VERSION=$(node -v 2>/dev/null)
+ msg_info "Current version: $CURRENT_FULL_VERSION - checking for updates"
+
+ # Try to install latest patch version
+ install_nodejs_from_binary "$NODE_VERSION" || {
+ msg_warn "Failed to check for Node.js updates, keeping current version"
+ }
+ fi
# Just update npm to latest
$STD npm install -g npm@latest 2>/dev/null || true
@@ -3601,7 +4266,7 @@ function setup_nodejs() {
msg_info "Upgrade Node.js from $CURRENT_NODE_VERSION to $NODE_VERSION"
remove_old_tool_version "nodejs"
else
- msg_info "Setup Node.js $NODE_VERSION"
+ msg_info "Setup Node.js $NODE_VERSION (method: $NODE_INSTALL_METHOD)"
fi
# Remove ALL Debian nodejs packages BEFORE adding NodeSource repo
@@ -3615,27 +4280,42 @@ function setup_nodejs() {
# Remove any APT pinning (not needed)
rm -f /etc/apt/preferences.d/nodesource 2>/dev/null || true
- # Prepare repository (cleanup + validation)
- prepare_repository_setup "nodesource" || {
- msg_error "Failed to prepare Node.js repository"
- return 1
- }
+ # Choose installation method
+ if [[ "$NODE_INSTALL_METHOD" == "binary" ]]; then
+ # Method 1: Install from official nodejs.org prebuilt binaries (no repo needed)
+ msg_info "Installing Node.js from official binaries"
+ ensure_dependencies curl ca-certificates
- # Setup NodeSource repository
- manage_tool_repository "nodejs" "$NODE_VERSION" "https://deb.nodesource.com/node_${NODE_VERSION}.x" "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" || {
- msg_error "Failed to setup Node.js repository"
- return 1
- }
+ install_nodejs_from_binary "$NODE_VERSION" || {
+ msg_error "Failed to install Node.js from binary"
+ return 1
+ }
+ else
+ # Method 2: Install from NodeSource APT repository (traditional method)
+ msg_info "Installing Node.js from NodeSource repository"
- # Force APT cache refresh after repository setup
- $STD apt update
+ # Prepare repository (cleanup + validation)
+ prepare_repository_setup "nodesource" || {
+ msg_error "Failed to prepare Node.js repository"
+ return 1
+ }
- ensure_dependencies curl ca-certificates gnupg
+ # Setup NodeSource repository
+ manage_tool_repository "nodejs" "$NODE_VERSION" "https://deb.nodesource.com/node_${NODE_VERSION}.x" "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" || {
+ msg_error "Failed to setup Node.js repository"
+ return 1
+ }
- install_packages_with_retry "nodejs" || {
- msg_error "Failed to install Node.js ${NODE_VERSION} from NodeSource"
- return 1
- }
+ # Force APT cache refresh after repository setup
+ $STD apt update
+
+ ensure_dependencies curl ca-certificates gnupg
+
+ install_packages_with_retry "nodejs" || {
+ msg_error "Failed to install Node.js ${NODE_VERSION} from NodeSource"
+ return 1
+ }
+ fi
# Verify Node.js was installed correctly
if ! command -v node >/dev/null 2>&1; then
@@ -3699,19 +4379,19 @@ function setup_nodejs() {
# Check if the module is already installed
if $STD npm list -g --depth=0 "$MODULE_NAME" 2>&1 | grep -q "$MODULE_NAME@"; then
- MODULE_INSTALLED_VERSION="$($STD npm list -g --depth=0 "$MODULE_NAME" 2>&1 | grep "$MODULE_NAME@" | awk -F@ '{print $2}' | tr -d '[:space:]')"
+ MODULE_INSTALLED_VERSION="$(npm list -g --depth=0 "$MODULE_NAME" 2>&1 | grep "$MODULE_NAME@" | awk -F@ '{print $2}' 2>/dev/null | tr -d '[:space:]' || echo '')"
if [[ "$MODULE_REQ_VERSION" != "latest" && "$MODULE_REQ_VERSION" != "$MODULE_INSTALLED_VERSION" ]]; then
msg_info "Updating $MODULE_NAME from v$MODULE_INSTALLED_VERSION to v$MODULE_REQ_VERSION"
if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}" 2>/dev/null; then
msg_warn "Failed to update $MODULE_NAME to version $MODULE_REQ_VERSION"
- ((failed_modules++))
+ ((failed_modules++)) || true
continue
fi
elif [[ "$MODULE_REQ_VERSION" == "latest" ]]; then
msg_info "Updating $MODULE_NAME to latest version"
if ! $STD npm install -g "${MODULE_NAME}@latest" 2>/dev/null; then
msg_warn "Failed to update $MODULE_NAME to latest version"
- ((failed_modules++))
+ ((failed_modules++)) || true
continue
fi
fi
@@ -3719,7 +4399,7 @@ function setup_nodejs() {
msg_info "Installing $MODULE_NAME@$MODULE_REQ_VERSION"
if ! $STD npm install -g "${MODULE_NAME}@${MODULE_REQ_VERSION}" 2>/dev/null; then
msg_warn "Failed to install $MODULE_NAME@$MODULE_REQ_VERSION"
- ((failed_modules++))
+ ((failed_modules++)) || true
continue
fi
fi
@@ -3808,17 +4488,26 @@ EOF
return 1
}
- manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || {
- msg_error "Failed to setup PHP repository"
- return 1
- }
+ # Use different repository based on OS
+ if [[ "$DISTRO_ID" == "ubuntu" ]]; then
+ # Ubuntu: Use ondrej/php PPA
+ msg_info "Adding ondrej/php PPA for Ubuntu"
+ $STD apt install -y software-properties-common
+ $STD add-apt-repository -y ppa:ondrej/php
+ else
+ # Debian: Use Sury repository
+ manage_tool_repository "php" "$PHP_VERSION" "" "https://packages.sury.org/debsuryorg-archive-keyring.deb" || {
+ msg_error "Failed to setup PHP repository"
+ return 1
+ }
+ fi
ensure_apt_working || return 1
$STD apt update
# Get available PHP version from repository
local AVAILABLE_PHP_VERSION=""
- AVAILABLE_PHP_VERSION=$(apt-cache show "php${PHP_VERSION}" 2>/dev/null | grep -m1 "^Version:" | awk '{print $2}' | cut -d- -f1) || true
+ AVAILABLE_PHP_VERSION=$(apt-cache show "php${PHP_VERSION}" 2>/dev/null | grep -m1 "^Version:" | awk '{print $2}' 2>/dev/null | cut -d- -f1 || true)
if [[ -z "$AVAILABLE_PHP_VERSION" ]]; then
msg_error "PHP ${PHP_VERSION} not found in configured repositories"
@@ -3959,6 +4648,11 @@ function setup_postgresql() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
+ # Ensure non-interactive mode for all apt operations
+ export DEBIAN_FRONTEND=noninteractive
+ export NEEDRESTART_MODE=a
+ export NEEDRESTART_SUSPEND=1
+
# Get currently installed version
local CURRENT_PG_VERSION=""
if command -v psql >/dev/null; then
@@ -4416,6 +5110,11 @@ function setup_clickhouse() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
+ # Ensure non-interactive mode for all apt operations
+ export DEBIAN_FRONTEND=noninteractive
+ export NEEDRESTART_MODE=a
+ export NEEDRESTART_SUSPEND=1
+
# Resolve "latest" version
if [[ "$CLICKHOUSE_VERSION" == "latest" ]]; then
CLICKHOUSE_VERSION=$(curl -fsSL --max-time 15 https://packages.clickhouse.com/tgz/stable/ 2>/dev/null |
@@ -4478,7 +5177,6 @@ function setup_clickhouse() {
"main"
# Install packages with retry logic
- export DEBIAN_FRONTEND=noninteractive
$STD apt update || {
msg_error "APT update failed for ClickHouse repository"
return 1
@@ -4620,7 +5318,7 @@ function setup_rust() {
# Check if already installed
if echo "$CRATE_LIST" | grep -q "^${NAME} "; then
- INSTALLED_VER=$(echo "$CRATE_LIST" | grep "^${NAME} " | head -1 | awk '{print $2}' | tr -d 'v:')
+ INSTALLED_VER=$(echo "$CRATE_LIST" | grep "^${NAME} " | head -1 | awk '{print $2}' 2>/dev/null | tr -d 'v:' || echo '')
if [[ -n "$VER" && "$VER" != "$INSTALLED_VER" ]]; then
msg_info "Upgrading $NAME from v$INSTALLED_VER to v$VER"
@@ -4635,7 +5333,7 @@ function setup_rust() {
msg_error "Failed to upgrade $NAME"
return 1
}
- local NEW_VER=$(cargo install --list 2>/dev/null | grep "^${NAME} " | head -1 | awk '{print $2}' | tr -d 'v:')
+ local NEW_VER=$(cargo install --list 2>/dev/null | grep "^${NAME} " | head -1 | awk '{print $2}' 2>/dev/null | tr -d 'v:' || echo 'unknown')
msg_ok "Upgraded $NAME to v$NEW_VER"
else
msg_ok "$NAME v$INSTALLED_VER already installed"
@@ -4653,7 +5351,7 @@ function setup_rust() {
msg_error "Failed to install $NAME"
return 1
}
- local NEW_VER=$(cargo install --list 2>/dev/null | grep "^${NAME} " | head -1 | awk '{print $2}' | tr -d 'v:')
+ local NEW_VER=$(cargo install --list 2>/dev/null | grep "^${NAME} " | head -1 | awk '{print $2}' 2>/dev/null | tr -d 'v:' || echo 'unknown')
msg_ok "Installed $NAME v$NEW_VER"
fi
fi
@@ -4975,7 +5673,7 @@ function setup_docker() {
# Install or upgrade Docker
if [ "$docker_installed" = true ]; then
msg_info "Checking for Docker updates"
- DOCKER_LATEST_VERSION=$(apt-cache policy docker-ce | grep Candidate | awk '{print $2}' | cut -d':' -f2 | cut -d'-' -f1)
+ DOCKER_LATEST_VERSION=$(apt-cache policy docker-ce | grep Candidate | awk '{print $2}' 2>/dev/null | cut -d':' -f2 | cut -d'-' -f1 || echo '')
if [ "$DOCKER_CURRENT_VERSION" != "$DOCKER_LATEST_VERSION" ]; then
msg_info "Updating Docker $DOCKER_CURRENT_VERSION β $DOCKER_LATEST_VERSION"
diff --git a/misc/vm-core.func b/misc/vm-core.func
index 099999de7..5412eb14c 100644
--- a/misc/vm-core.func
+++ b/misc/vm-core.func
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# License: MIT | https://git.community-scripts.org/community-scripts/ProxmoxVED/raw/branch/main/LICENSE
set -euo pipefail
diff --git a/tools/addon/_template.sh b/tools/addon/_template.sh
index e184da29f..39851fef7 100644
--- a/tools/addon/_template.sh
+++ b/tools/addon/_template.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: YourName
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://example.com/project
diff --git a/tools/addon/add-iptag.sh b/tools/addon/add-iptag.sh
index c3bf88cf9..b0c02e6e4 100644
--- a/tools/addon/add-iptag.sh
+++ b/tools/addon/add-iptag.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz) && Desert_Gamer
# License: MIT
# Source: https://github.com/gitsang/iptag
@@ -200,7 +200,7 @@ ip_in_cidrs() {
is_valid_ipv4() {
local ip="$1"
[[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
-
+
local IFS='.' parts
read -ra parts <<< "$ip"
for part in "${parts[@]}"; do
@@ -340,14 +340,14 @@ check_status() {
update_all() {
local type="$1" list_cmd="pct" vmids count=0
[[ "$type" == "vm" ]] && list_cmd="qm"
-
+
vmids=$($list_cmd list 2>/dev/null | grep -v VMID | awk '{print $1}')
for vmid in $vmids; do ((count++)); done
-
+
echo "Found ${count} running ${type}s"
[[ $count -eq 0 ]] && return
- for vmid in $vmids; do
+ for vmid in $vmids; do
update_tags "$type" "$vmid"
done
}
@@ -361,7 +361,7 @@ check() {
local interval_var="${type^^}_STATUS_CHECK_INTERVAL"
local last_check_var="last_${type}_check_time"
local last_update_var="last_update_${type}_time"
-
+
if [[ "${!interval_var}" -gt 0 ]] && (( current_time - ${!last_check_var} >= ${!interval_var} )); then
echo "Checking ${type^^} status..."
eval "${last_check_var}=\$current_time"
diff --git a/tools/addon/code-server.sh b/tools/addon/code-server.sh
index d2700a2bb..7d1c3b720 100644
--- a/tools/addon/code-server.sh
+++ b/tools/addon/code-server.sh
@@ -1,18 +1,18 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
function header_info {
cat <<"EOF"
- ______ __ _____
+ ______ __ _____
/ ____/___ ____/ /__ / ___/___ ______ _____ _____
/ / / __ \/ __ / _ \ \__ \/ _ \/ ___/ | / / _ \/ ___/
-/ /___/ /_/ / /_/ / __/ ___/ / __/ / | |/ / __/ /
-\____/\____/\__,_/\___/ /____/\___/_/ |___/\___/_/
-
+/ /___/ /_/ / /_/ / __/ ___/ / __/ / | |/ / __/ /
+\____/\____/\__,_/\___/ /____/\___/_/ |___/\___/_/
+
EOF
}
IP=$(hostname -I | awk '{print $1}')
@@ -86,7 +86,7 @@ systemctl enable -q --now code-server@$USER
cat <~/.config/code-server/config.yaml
bind-addr: 0.0.0.0:8680
auth: none
-password:
+password:
cert: false
EOF
systemctl restart code-server@$USER
diff --git a/tools/addon/copyparty.sh b/tools/addon/copyparty.sh
index 98f7ad72d..cf9451a0a 100644
--- a/tools/addon/copyparty.sh
+++ b/tools/addon/copyparty.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/9001/copyparty
diff --git a/tools/addon/filebrowser-quantum.sh b/tools/addon/filebrowser-quantum.sh
index 74911a788..7cad2a477 100644
--- a/tools/addon/filebrowser-quantum.sh
+++ b/tools/addon/filebrowser-quantum.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/addon/filebrowser.sh b/tools/addon/filebrowser.sh
index b648c1555..8fcb4824b 100644
--- a/tools/addon/filebrowser.sh
+++ b/tools/addon/filebrowser.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | Co-Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/addon/glances.sh b/tools/addon/glances.sh
index 0f1b76f11..2928fe46f 100644
--- a/tools/addon/glances.sh
+++ b/tools/addon/glances.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/addon/grafana-loki.sh b/tools/addon/grafana-loki.sh
index b68a80478..9d7822729 100644
--- a/tools/addon/grafana-loki.sh
+++ b/tools/addon/grafana-loki.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/tools/addon/jellystat.sh b/tools/addon/jellystat.sh
deleted file mode 100644
index 7975d0d22..000000000
--- a/tools/addon/jellystat.sh
+++ /dev/null
@@ -1,384 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: MickLesk (CanbiZ)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/CyferShepard/Jellystat
-
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/core.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/tools.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/error_handler.func)
-
-# Enable error handling
-set -Eeuo pipefail
-trap 'error_handler' ERR
-
-# ==============================================================================
-# CONFIGURATION
-# ==============================================================================
-APP="Jellystat"
-APP_TYPE="addon"
-INSTALL_PATH="/opt/jellystat"
-CONFIG_PATH="/opt/jellystat/.env"
-DEFAULT_PORT=3000
-
-# Initialize all core functions (colors, formatting, icons, STD mode)
-load_functions
-
-# ==============================================================================
-# HEADER
-# ==============================================================================
-function header_info {
- clear
- cat <<"EOF"
- __ ____ __ __
- / /__ / / /_ _______/ /_____ _/ /_
- __ / / _ \/ / / / / / ___/ __/ __ `/ __/
-/ /_/ / __/ / / /_/ (__ ) /_/ /_/ / /_
-\____/\___/_/_/\__, /____/\__/\__,_/\__/
- /____/
-EOF
-}
-
-# ==============================================================================
-# HELPER FUNCTIONS
-# ==============================================================================
-get_ip() {
- hostname -I 2>/dev/null | awk '{print $1}' || echo "127.0.0.1"
-}
-
-# ==============================================================================
-# OS DETECTION
-# ==============================================================================
-if [[ -f "/etc/alpine-release" ]]; then
- msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
- exit 1
-elif [[ -f "/etc/debian_version" ]]; then
- OS="Debian"
- SERVICE_PATH="/etc/systemd/system/jellystat.service"
-else
- echo -e "${CROSS} Unsupported OS detected. Exiting."
- exit 1
-fi
-
-# ==============================================================================
-# UNINSTALL
-# ==============================================================================
-function uninstall() {
- msg_info "Uninstalling ${APP}"
- systemctl disable --now jellystat.service &>/dev/null || true
- rm -f "$SERVICE_PATH"
- rm -rf "$INSTALL_PATH"
- rm -f "/usr/local/bin/update_jellystat"
- rm -f "$HOME/.jellystat"
- msg_ok "${APP} has been uninstalled"
-
- # Ask about PostgreSQL database removal
- echo ""
- echo -n "${TAB}Also remove PostgreSQL database 'jellystat'? (y/N): "
- read -r db_prompt
- if [[ "${db_prompt,,}" =~ ^(y|yes)$ ]]; then
- if command -v psql &>/dev/null; then
- msg_info "Removing PostgreSQL database and user"
- $STD sudo -u postgres psql -c "DROP DATABASE IF EXISTS jellystat;" &>/dev/null || true
- $STD sudo -u postgres psql -c "DROP USER IF EXISTS jellystat;" &>/dev/null || true
- msg_ok "Removed PostgreSQL database 'jellystat' and user 'jellystat'"
- else
- msg_warn "PostgreSQL not found - database may have been removed already"
- fi
- else
- msg_warn "PostgreSQL database was NOT removed. Remove manually if needed:"
- echo -e "${TAB} sudo -u postgres psql -c \"DROP DATABASE jellystat;\""
- echo -e "${TAB} sudo -u postgres psql -c \"DROP USER jellystat;\""
- fi
-}
-
-# ==============================================================================
-# UPDATE
-# ==============================================================================
-function update() {
- if check_for_gh_release "jellystat" "CyferShepard/Jellystat"; then
- msg_info "Stopping service"
- systemctl stop jellystat.service &>/dev/null || true
- msg_ok "Stopped service"
-
- msg_info "Backing up configuration"
- cp "$CONFIG_PATH" /tmp/jellystat.env.bak 2>/dev/null || true
- msg_ok "Backed up configuration"
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
-
- msg_info "Restoring configuration"
- cp /tmp/jellystat.env.bak "$CONFIG_PATH" 2>/dev/null || true
- rm -f /tmp/jellystat.env.bak
- msg_ok "Restored configuration"
-
- msg_info "Installing dependencies"
- cd "$INSTALL_PATH"
- $STD npm install
- msg_ok "Installed dependencies"
-
- msg_info "Building ${APP}"
- $STD npm run build
- msg_ok "Built ${APP}"
-
- msg_info "Starting service"
- systemctl start jellystat
- msg_ok "Started service"
- msg_ok "Updated successfully"
- exit
- fi
-}
-
-# ==============================================================================
-# INSTALL
-# ==============================================================================
-function install() {
- local ip
- ip=$(get_ip)
-
- # Setup Node.js (only installs if not present or different version)
- if command -v node &>/dev/null; then
- msg_ok "Node.js already installed ($(node -v))"
- else
- NODE_VERSION="22" setup_nodejs
- fi
-
- # Setup PostgreSQL (only installs if not present)
- if command -v psql &>/dev/null; then
- msg_ok "PostgreSQL already installed"
- else
- PG_VERSION="17" setup_postgresql
- fi
-
- # Create database and user (skip if already exists)
- local DB_NAME="jellystat"
- local DB_USER="jellystat"
- local DB_PASS
-
- msg_info "Setting up PostgreSQL database"
-
- # Check if database already exists
- if sudo -u postgres psql -lqt 2>/dev/null | cut -d \| -f 1 | grep -qw "$DB_NAME"; then
- msg_warn "Database '${DB_NAME}' already exists - skipping creation"
- echo -n "${TAB}Enter existing database password for '${DB_USER}': "
- read -rs DB_PASS
- echo ""
- else
- # Generate new password
- DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c16)
-
- # Check if user exists, create if not
- if sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" 2>/dev/null | grep -q 1; then
- msg_info "User '${DB_USER}' exists, updating password"
- $STD sudo -u postgres psql -c "ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASS}';" || {
- msg_error "Failed to update PostgreSQL user"
- return 1
- }
- else
- $STD sudo -u postgres psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}';" || {
- msg_error "Failed to create PostgreSQL user"
- return 1
- }
- fi
-
- # Create database (use template0 for UTF8 encoding compatibility)
- $STD sudo -u postgres psql -c "CREATE DATABASE ${DB_NAME} WITH OWNER ${DB_USER} ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0;" || {
- msg_error "Failed to create PostgreSQL database"
- return 1
- }
- $STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};" || {
- msg_error "Failed to grant privileges"
- return 1
- }
-
- # Grant schema permissions (required for PostgreSQL 15+)
- $STD sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO ${DB_USER};" || true
-
- # Configure pg_hba.conf for password authentication on localhost
- local PG_HBA
- PG_HBA=$(sudo -u postgres psql -tAc "SHOW hba_file;" 2>/dev/null | tr -d ' ')
- if [[ -n "$PG_HBA" && -f "$PG_HBA" ]]; then
- # Check if md5/scram-sha-256 auth is already configured for local connections
- if ! grep -qE "^host\s+${DB_NAME}\s+${DB_USER}\s+127.0.0.1" "$PG_HBA"; then
- msg_info "Configuring PostgreSQL authentication"
- # Add password auth for jellystat user on localhost (before the default rules)
- sed -i "/^# IPv4 local connections:/a host ${DB_NAME} ${DB_USER} 127.0.0.1/32 scram-sha-256" "$PG_HBA"
- sed -i "/^# IPv4 local connections:/a host ${DB_NAME} ${DB_USER} ::1/128 scram-sha-256" "$PG_HBA"
- # Reload PostgreSQL to apply changes
- systemctl reload postgresql
- msg_ok "Configured PostgreSQL authentication"
- fi
- fi
-
- msg_ok "Created PostgreSQL database '${DB_NAME}'"
- fi
-
- # Generate JWT Secret
- local JWT_SECRET
- JWT_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
-
- # Force fresh download by removing version cache
- rm -f "$HOME/.jellystat"
- mkdir -p "$INSTALL_PATH"
- fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
-
- msg_info "Installing dependencies"
- cd "$INSTALL_PATH" || {
- msg_error "Failed to enter ${INSTALL_PATH}"
- return 1
- }
- $STD npm install
- msg_ok "Installed dependencies"
-
- msg_info "Building ${APP}"
- $STD npm run build
- msg_ok "Built ${APP}"
-
- msg_info "Creating configuration"
- cat <"$CONFIG_PATH"
-# Jellystat Configuration
-# Database
-POSTGRES_USER=${DB_USER}
-POSTGRES_PASSWORD=${DB_PASS}
-POSTGRES_IP=localhost
-POSTGRES_PORT=5432
-POSTGRES_DB=${DB_NAME}
-
-# Security
-JWT_SECRET=${JWT_SECRET}
-
-# Server
-JS_LISTEN_IP=0.0.0.0
-JS_BASE_URL=/
-TZ=$(cat /etc/timezone 2>/dev/null || echo "UTC")
-
-# Optional: GeoLite for IP Geolocation
-# JS_GEOLITE_ACCOUNT_ID=
-# JS_GEOLITE_LICENSE_KEY=
-
-# Optional: Master Override (if you forget your password)
-# JS_USER=admin
-# JS_PASSWORD=admin
-
-# Optional: Minimum playback duration to record (seconds)
-# MINIMUM_SECONDS_TO_INCLUDE_PLAYBACK=1
-
-# Optional: Self-signed certificates
-REJECT_SELF_SIGNED_CERTIFICATES=true
-EOF
- chmod 600 "$CONFIG_PATH"
- msg_ok "Created configuration"
-
- msg_info "Creating service"
- cat <"$SERVICE_PATH"
-[Unit]
-Description=Jellystat - Statistics for Jellyfin
-After=network.target postgresql.service
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=${INSTALL_PATH}
-EnvironmentFile=${CONFIG_PATH}
-ExecStart=/usr/bin/node ${INSTALL_PATH}/backend/server.js
-Restart=always
-RestartSec=10
-
-[Install]
-WantedBy=multi-user.target
-EOF
- systemctl enable --now jellystat &>/dev/null
- msg_ok "Created and started service"
-
- # Create update script (simple wrapper that calls this addon with type=update)
- msg_info "Creating update script"
- cat <<'UPDATEEOF' >/usr/local/bin/update_jellystat
-#!/usr/bin/env bash
-# Jellystat Update Script
-type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/tools/addon/jellystat.sh)"
-UPDATEEOF
- chmod +x /usr/local/bin/update_jellystat
- msg_ok "Created update script (/usr/local/bin/update_jellystat)"
-
- # Save credentials
- local CREDS_FILE="/root/jellystat.creds"
- cat <"$CREDS_FILE"
-Jellystat Credentials
-=====================
-Database User: ${DB_USER}
-Database Password: ${DB_PASS}
-Database Name: ${DB_NAME}
-JWT Secret: ${JWT_SECRET}
-
-Web UI: http://${ip}:${DEFAULT_PORT}
-EOF
- chmod 600 "$CREDS_FILE"
-
- echo ""
- msg_ok "${APP} is reachable at: ${BL}http://${ip}:${DEFAULT_PORT}${CL}"
- msg_ok "Credentials saved to: ${BL}${CREDS_FILE}${CL}"
- echo ""
- msg_warn "On first access, you'll need to configure your Jellyfin server connection."
-}
-
-# ==============================================================================
-# MAIN
-# ==============================================================================
-
-# Handle type=update (called from update script)
-if [[ "${type:-}" == "update" ]]; then
- header_info
- if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/package.json" ]]; then
- update
- else
- msg_error "${APP} is not installed. Nothing to update."
- exit 1
- fi
- exit 0
-fi
-
-header_info
-
-IP=$(get_ip)
-
-# Check if already installed
-if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/package.json" ]]; then
- msg_warn "${APP} is already installed."
- echo ""
-
- echo -n "${TAB}Uninstall ${APP}? (y/N): "
- read -r uninstall_prompt
- if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
- uninstall
- exit 0
- fi
-
- echo -n "${TAB}Update ${APP}? (y/N): "
- read -r update_prompt
- if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
- update
- exit 0
- fi
-
- msg_warn "No action selected. Exiting."
- exit 0
-fi
-
-# Fresh installation
-msg_warn "${APP} is not installed."
-echo ""
-echo -e "${TAB}${INFO} This will install:"
-echo -e "${TAB} - Node.js 22"
-echo -e "${TAB} - PostgreSQL 17"
-echo -e "${TAB} - Jellystat"
-echo ""
-
-echo -n "${TAB}Install ${APP}? (y/N): "
-read -r install_prompt
-if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
- install
-else
- msg_warn "Installation cancelled. Exiting."
- exit 0
-fi
diff --git a/tools/addon/netdata.sh b/tools/addon/netdata.sh
index cab0c8081..8d7d3a263 100644
--- a/tools/addon/netdata.sh
+++ b/tools/addon/netdata.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -132,7 +132,7 @@ install() {
$STD apt-get update
$STD apt-get install -y netdata
msg_ok "Installed Netdata"
- msg_ok "Completed Successfully!\n"
+ msg_ok "Completed successfully!\n"
echo -e "\n Netdata should be reachable at${BL} http://$(hostname -I | awk '{print $1}'):19999 ${CL}\n"
}
@@ -150,7 +150,7 @@ uninstall() {
$STD apt autoremove -y
$STD userdel netdata || true
msg_ok "Uninstalled Netdata"
- msg_ok "Completed Successfully!\n"
+ msg_ok "Completed successfully!\n"
}
header_info
diff --git a/tools/addon/pihole-exporter.sh b/tools/addon/pihole-exporter.sh
deleted file mode 100644
index f9c60bf3d..000000000
--- a/tools/addon/pihole-exporter.sh
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: CrazyWolf13
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/eko/pihole-exporter/
-
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/core.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/tools.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/error_handler.func)
-load_functions
-
-# Enable error handling
-set -Eeuo pipefail
-trap 'error_handler' ERR
-
-# ==============================================================================
-# CONFIGURATION
-# ==============================================================================
-VERBOSE=${var_verbose:-no}
-APP="pihole-exporter"
-APP_TYPE="tools"
-INSTALL_PATH="/opt/pihole-exporter"
-CONFIG_PATH="/opt/pihole-exporter.env"
-header_info
-ensure_usr_local_bin_persist
-get_current_ip &>/dev/null
-
-# ==============================================================================
-# OS DETECTION
-# ==============================================================================
-if [[ -f "/etc/alpine-release" ]]; then
- OS="Alpine"
- SERVICE_PATH="/etc/init.d/pihole-exporter"
-elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
- OS="Debian"
- SERVICE_PATH="/etc/systemd/system/pihole-exporter.service"
-else
- echo -e "${CROSS} Unsupported OS detected. Exiting."
- exit 1
-fi
-
-# ==============================================================================
-# UNINSTALL
-# ==============================================================================
-function uninstall() {
- msg_info "Uninstalling Pihole-Exporter"
- if [[ "$OS" == "Alpine" ]]; then
- rc-service pihole-exporter stop &>/dev/null
- rc-update del pihole-exporter &>/dev/null
- rm -f "$SERVICE_PATH"
- else
- systemctl disable -q --now pihole-exporter
- rm -f "$SERVICE_PATH"
- fi
- rm -rf "$INSTALL_PATH" "$CONFIG_PATH"
- rm -f "/usr/local/bin/update_pihole-exporter"
- rm -f "$HOME/.pihole-exporter"
- msg_ok "Pihole-Exporter has been uninstalled"
-}
-
-# ==============================================================================
-# UPDATE
-# ==============================================================================
-function update() {
- if check_for_gh_release "pihole-exporter" "eko/pihole-exporter"; then
- msg_info "Stopping service"
- if [[ "$OS" == "Alpine" ]]; then
- rc-service pihole-exporter stop &>/dev/null
- else
- systemctl stop pihole-exporter
- fi
- msg_ok "Stopped service"
-
- fetch_and_deploy_gh_release "pihole-exporter" "eko/pihole-exporter" "tarball" "latest"
- setup_go
-
- msg_info "Building Pihole-Exporter"
- cd /opt/pihole-exporter/
- $STD /usr/local/bin/go build -o ./pihole-exporter
- msg_ok "Built Pihole-Exporter"
-
- msg_info "Starting service"
- if [[ "$OS" == "Alpine" ]]; then
- rc-service pihole-exporter start &>/dev/null
- else
- systemctl start pihole-exporter
- fi
- msg_ok "Started service"
- msg_ok "Updated successfully"
- exit
- fi
-}
-
-# ==============================================================================
-# INSTALL
-# ==============================================================================
-function install() {
- read -erp "Enter the protocol to use (http/https), default https: " pihole_PROTOCOL
- read -erp "Enter the hostname of Pihole, example: (127.0.0.1): " pihole_HOSTNAME
- read -erp "Enter the port of Pihole, default 443: " pihole_PORT
- read -rsp "Enter Pihole password: " pihole_PASSWORD
- printf "\n"
- read -erp "Do you want to skip TLS-Verification (if using a self-signed Certificate on Pi-Hole) [y/N]: " SKIP_TLS
- if [[ "${SKIP_TLS,,}" =~ ^(y|yes)$ ]]; then
- pihole_SKIP_TLS="true"
- fi
-
- fetch_and_deploy_gh_release "pihole-exporter" "eko/pihole-exporter" "tarball" "latest"
- setup_go
- msg_info "Building Pihole-Exporter on ${OS}"
- cd /opt/pihole-exporter/
- $STD /usr/local/bin/go build -o ./pihole-exporter
- msg_ok "Built Pihole-Exporter"
-
- msg_info "Creating configuration"
- cat <"$CONFIG_PATH"
-# https://github.com/eko/pihole-exporter/?tab=readme-ov-file#available-cli-options
-PIHOLE_PASSWORD="${pihole_PASSWORD}"
-PIHOLE_HOSTNAME="${pihole_HOSTNAME:-127.0.0.1}"
-PIHOLE_PORT="${pihole_PORT:-443}"
-SKIP_TLS_VERIFICATION="${pihole_SKIP_TLS:-false}"
-PIHOLE_PROTOCOL="${pihole_PROTOCOL:-https}"
-EOF
- msg_ok "Created configuration"
-
- msg_info "Creating service"
- if [[ "$OS" == "Debian" ]]; then
- cat <"$SERVICE_PATH"
-[Unit]
-Description=pihole-exporter
-After=network.target
-
-[Service]
-User=root
-WorkingDirectory=/opt/pihole-exporter
-EnvironmentFile=$CONFIG_PATH
-ExecStart=/opt/pihole-exporter/pihole-exporter
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-EOF
- systemctl daemon-reload
- systemctl enable -q --now pihole-exporter
- else
- cat <"$SERVICE_PATH"
-#!/sbin/openrc-run
-
-name="pihole-exporter"
-description="Pi-hole Exporter for Prometheus"
-command="${INSTALL_PATH}/pihole-exporter"
-command_background=true
-directory="/opt/pihole-exporter"
-pidfile="/run/\${RC_SVCNAME}.pid"
-output_log="/var/log/pihole-exporter.log"
-error_log="/var/log/pihole-exporter.log"
-
-depend() {
- need net
- after firewall
-}
-
-start_pre() {
- if [ -f "$CONFIG_PATH" ]; then
- export \$(grep -v '^#' $CONFIG_PATH | xargs)
- fi
-}
-EOF
- chmod +x "$SERVICE_PATH"
- $STD rc-update add pihole-exporter default
- $STD rc-service pihole-exporter start
- fi
- msg_ok "Created and started service"
-
- # Create update script
- msg_info "Creating update script"
- cat <<'UPDATEEOF' >/usr/local/bin/update_pihole-exporter
-#!/usr/bin/env bash
-# pihole-exporter Update Script
-type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/tools/addon/pihole-exporter.sh)"
-UPDATEEOF
- chmod +x /usr/local/bin/update_pihole-exporter
- msg_ok "Created update script (/usr/local/bin/update_pihole-exporter)"
-
- echo ""
- msg_ok "Pihole-Exporter installed successfully"
- msg_ok "Metrics: ${BL}http://${CURRENT_IP}:9617/metrics${CL}"
- msg_ok "Config: ${BL}${CONFIG_PATH}${CL}"
-}
-
-# ==============================================================================
-# MAIN
-# ==============================================================================
-header_info
-ensure_usr_local_bin_persist
-get_current_ip &>/dev/null
-
-# Handle type=update (called from update script)
-if [[ "${type:-}" == "update" ]]; then
- if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/pihole-exporter" ]]; then
- update
- else
- msg_error "Pihole-Exporter is not installed. Nothing to update."
- exit 1
- fi
- exit 0
-fi
-
-# Check if already installed
-if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/pihole-exporter" ]]; then
- msg_warn "Pihole-Exporter is already installed."
- echo ""
-
- echo -n "${TAB}Uninstall Pihole-Exporter? (y/N): "
- read -r uninstall_prompt
- if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
- uninstall
- exit 0
- fi
-
- echo -n "${TAB}Update Pihole-Exporter? (y/N): "
- read -r update_prompt
- if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
- update
- exit 0
- fi
-
- msg_warn "No action selected. Exiting."
- exit 0
-fi
-
-# Fresh installation
-msg_warn "Pihole-Exporter is not installed."
-echo ""
-echo -e "${TAB}${INFO} This will install:"
-echo -e "${TAB} - Pi-hole Exporter (Go binary)"
-echo -e "${TAB} - Systemd/OpenRC service"
-echo ""
-
-echo -n "${TAB}Install Pihole-Exporter? (y/N): "
-read -r install_prompt
-if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
- install
-else
- msg_warn "Installation cancelled. Exiting."
- exit 0
-fi
diff --git a/tools/addon/qbittorrent-exporter.sh b/tools/addon/qbittorrent-exporter.sh
deleted file mode 100644
index 03e459803..000000000
--- a/tools/addon/qbittorrent-exporter.sh
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2025 community-scripts ORG
-# Author: CrazyWolf13
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/martabal/qbittorrent-exporter
-
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/core.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/tools.func)
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func)
-
-VERBOSE=${var_verbose:-no}
-APP="qbittorrent-exporter"
-APP_TYPE="tools"
-INSTALL_PATH="/opt/qbittorrent-exporter/src/qbittorrent-exporter"
-CONFIG_PATH="/opt/qbittorrent-exporter.env"
-header_info
-ensure_usr_local_bin_persist
-get_current_ip &>/dev/null
-
-# OS Detection
-if [[ -f "/etc/alpine-release" ]]; then
- OS="Alpine"
- SERVICE_PATH="/etc/init.d/qbittorrent-exporter"
-elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
- OS="Debian"
- SERVICE_PATH="/etc/systemd/system/qbittorrent-exporter.service"
-else
- echo -e "${CROSS} Unsupported OS detected. Exiting."
- exit 1
-fi
-
-# Existing installation
-if [[ -f "$INSTALL_PATH" ]]; then
- echo -e "${YW}β οΈ qbittorrent-exporter is already installed.${CL}"
- echo -n "Uninstall ${APP}? (y/N): "
- read -r uninstall_prompt
- if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
- msg_info "Uninstalling qbittorrent-exporter"
- if [[ "$OS" == "Debian" ]]; then
- systemctl disable --now qbittorrent-exporter.service &>/dev/null
- rm -f "$SERVICE_PATH"
- else
- rc-service qbittorrent-exporter stop &>/dev/null
- rc-update del qbittorrent-exporter &>/dev/null
- rm -f "$SERVICE_PATH"
- fi
- rm -f "$INSTALL_PATH" "$CONFIG_PATH" ~/.qbittorrent-exporter
- msg_ok "${APP} has been uninstalled."
- exit 0
- fi
-
- echo -n "Update qbittorrent-exporter? (y/N): "
- read -r update_prompt
- if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
- if check_for_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter"; then
- fetch_and_deploy_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter"
- setup_go
- msg_info "Updating qbittorrent-exporter"
- cd /opt/qbittorrent-exporter/src
- $STD /usr/local/bin/go build -o ./qbittorrent-exporter
- msg_ok "Updated Successfully!"
- fi
- exit 0
- else
- echo -e "${YW}β οΈ Update skipped. Exiting.${CL}"
- exit 0
- fi
-fi
-
-echo -e "${YW}β οΈ qbittorrent-exporter is not installed.${CL}"
-echo -n "Enter URL of qbittorrent, example: (http://127.0.0.1:8080): "
-read -er QBITTORRENT_BASE_URL
-
-echo -n "Enter qbittorrent username: "
-read -er QBITTORRENT_USERNAME
-
-echo -n "Enter qbittorrent password: "
-read -rs QBITTORRENT_PASSWORD
-echo
-
-echo -n "Install qbittorrent-exporter? (y/n): "
-read -r install_prompt
-if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
- echo -e "${YW}β οΈ Installation skipped. Exiting.${CL}"
- exit 0
-fi
-
-fetch_and_deploy_gh_release "qbittorrent-exporter" "martabal/qbittorrent-exporter" "tarball" "latest"
-setup_go
-msg_info "Installing qbittorrent-exporter on ${OS}"
-cd /opt/qbittorrent-exporter/src
-$STD /usr/local/bin/go build -o ./qbittorrent-exporter
-msg_ok "Installed qbittorrent-exporter"
-
-msg_info "Creating configuration"
-cat <"$CONFIG_PATH"
-# https://github.com/martabal/qbittorrent-exporter?tab=readme-ov-file#parameters
-QBITTORRENT_BASE_URL="${QBITTORRENT_BASE_URL}"
-QBITTORRENT_USERNAME="${QBITTORRENT_USERNAME}"
-QBITTORRENT_PASSWORD="${QBITTORRENT_PASSWORD}"
-EOF
-msg_ok "Created configuration"
-
-msg_info "Creating service"
-if [[ "$OS" == "Debian" ]]; then
- cat <"$SERVICE_PATH"
-[Unit]
-Description=qbittorrent-exporter
-After=network.target
-
-[Service]
-User=root
-WorkingDirectory=/opt/qbittorrent-exporter/src
-EnvironmentFile=$CONFIG_PATH
-ExecStart=/opt/qbittorrent-exporter/src/qbittorrent-exporter
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
-EOF
- systemctl enable -q --now qbittorrent-exporter
-else
- cat <"$SERVICE_PATH"
-#!/sbin/openrc-run
-
-command="$INSTALL_PATH"
-command_args=""
-command_background=true
-directory="/opt/qbittorrent-exporter/src"
-pidfile="/opt/qbittorrent-exporter/src/pidfile"
-
-depend() {
- need net
-}
-
-start_pre() {
- if [ -f "$CONFIG_PATH" ]; then
- export \$(grep -v '^#' $CONFIG_PATH | xargs)
- fi
-}
-EOF
- chmod +x "$SERVICE_PATH"
- rc-update add qbittorrent-exporter default &>/dev/null
- rc-service qbittorrent-exporter start &>/dev/null
-fi
-msg_ok "Service created successfully"
-
-echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$CURRENT_IP:8090/metrics${CL}"
diff --git a/tools/headers/_template b/tools/headers/_template
new file mode 100644
index 000000000..dddf1857d
--- /dev/null
+++ b/tools/headers/_template
@@ -0,0 +1,6 @@
+ο»Ώ __ ___ ___ __ __
+ / |/ /_ __/ | ____/ /___/ /___ ____
+ / /|_/ / / / / /| |/ __ / __ / __ \/ __ \
+ / / / / /_/ / ___ / /_/ / /_/ / /_/ / / / /
+/_/ /_/\__, /_/ |_\__,_/\__,_/\____/_/ /_/
+ /____/
diff --git a/tools/headers/add-iptag b/tools/headers/add-iptag
index 153ccd369..f4ed9970c 100644
--- a/tools/headers/add-iptag
+++ b/tools/headers/add-iptag
@@ -1,4 +1,4 @@
- ________ ______
+ο»Ώ ________ ______
/ _/ __ \ /_ __/___ _____ _
/ // /_/ /_____/ / / __ `/ __ `/
_/ // ____/_____/ / / /_/ / /_/ /
diff --git a/tools/headers/code-server b/tools/headers/code-server
index f9bd04768..156108c33 100644
--- a/tools/headers/code-server
+++ b/tools/headers/code-server
@@ -1,4 +1,4 @@
- ______ __ _____
+ο»Ώ ______ __ _____
/ ____/___ ____/ /__ / ___/___ ______ _____ _____
/ / / __ \/ __ / _ \ \__ \/ _ \/ ___/ | / / _ \/ ___/
/ /___/ /_/ / /_/ / __/ ___/ / __/ / | |/ / __/ /
diff --git a/tools/headers/container-restore-from-backup b/tools/headers/container-restore-from-backup
index dd7d0def1..9b133c0d1 100644
--- a/tools/headers/container-restore-from-backup
+++ b/tools/headers/container-restore-from-backup
@@ -1,4 +1,4 @@
- __ __ ___ _ __ __ ______ __ _
+ο»Ώ __ __ ___ _ __ __ ______ __ _
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / ____/___ ____ / /_____ _(_)___ ___ _____
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / __ \/ __ \/ __/ __ `/ / __ \/ _ \/ ___/
/ __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /___/ /_/ / / / / /_/ /_/ / / / / / __/ /
diff --git a/tools/headers/copyparty b/tools/headers/copyparty
index 7e072248d..0511b397f 100644
--- a/tools/headers/copyparty
+++ b/tools/headers/copyparty
@@ -1,4 +1,4 @@
- ______ ____ __
+ο»Ώ ______ ____ __
/ ____/___ ____ __ __/ __ \____ ______/ /___ __
/ / / __ \/ __ \/ / / / /_/ / __ `/ ___/ __/ / / /
/ /___/ /_/ / /_/ / /_/ / ____/ /_/ / / / /_/ /_/ /
diff --git a/tools/headers/core-restore-from-backup b/tools/headers/core-restore-from-backup
index d356da026..afb4bbc9e 100644
--- a/tools/headers/core-restore-from-backup
+++ b/tools/headers/core-restore-from-backup
@@ -1,4 +1,4 @@
- __ __ ___ _ __ __ ______
+ο»Ώ __ __ ___ _ __ __ ______
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / ____/___ ________
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / __ \/ ___/ _ \
/ __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /___/ /_/ / / / __/
diff --git a/tools/headers/filebrowser b/tools/headers/filebrowser
index 1f4b71a1a..e65eab18a 100644
--- a/tools/headers/filebrowser
+++ b/tools/headers/filebrowser
@@ -1,4 +1,4 @@
- _______ __ ____
+ο»Ώ _______ __ ____
/ ____(_) /__ / __ )_________ _ __________ _____
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ /
diff --git a/tools/headers/filebrowser-quantum b/tools/headers/filebrowser-quantum
index 95c8b4b87..e0d4e30e3 100644
--- a/tools/headers/filebrowser-quantum
+++ b/tools/headers/filebrowser-quantum
@@ -1,4 +1,4 @@
- _______ __ ____ ____ __
+ο»Ώ _______ __ ____ ____ __
/ ____(_) /__ / __ )_________ _ __________ _____ / __ \__ ______ _____ / /___ ______ ___
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/ / / / / / / / __ `/ __ \/ __/ / / / __ `__ \
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ / / /_/ / /_/ / /_/ / / / / /_/ /_/ / / / / / /
diff --git a/tools/headers/glances b/tools/headers/glances
index 18ac97577..4e35ca0d9 100644
--- a/tools/headers/glances
+++ b/tools/headers/glances
@@ -1,4 +1,4 @@
- ________
+ο»Ώ ________
/ ____/ /___ _____ ________ _____
/ / __/ / __ `/ __ \/ ___/ _ \/ ___/
/ /_/ / / /_/ / / / / /__/ __(__ )
diff --git a/tools/headers/meilisearch-ui b/tools/headers/meilisearch-ui
index fe37b6058..c90a9e839 100644
--- a/tools/headers/meilisearch-ui
+++ b/tools/headers/meilisearch-ui
@@ -1,4 +1,4 @@
- __ ___ _ ___ __ __ ______
+ο»Ώ __ ___ _ ___ __ __ ______
/ |/ /__ (_) (_)_______ ____ ___________/ /_ / / / / _/
/ /|_/ / _ \/ / / / ___/ _ \/ __ `/ ___/ ___/ __ \ / / / // /
/ / / / __/ / / (__ ) __/ /_/ / / / /__/ / / / / /_/ // /
diff --git a/tools/headers/oci-deploy b/tools/headers/oci-deploy
new file mode 100644
index 000000000..5a809b39b
--- /dev/null
+++ b/tools/headers/oci-deploy
@@ -0,0 +1,6 @@
+ο»Ώ ____ __________ ______ __ _
+ / __ \/ ____/ _/ / ____/___ ____ / /_____ _(_)___ ___ _____
+ / / / / / / /_____/ / / __ \/ __ \/ __/ __ `/ / __ \/ _ \/ ___/
+/ /_/ / /____/ /_____/ /___/ /_/ / / / / /_/ /_/ / / / / / __/ /
+\____/\____/___/ \____/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/
+
diff --git a/tools/headers/phpmyadmin b/tools/headers/phpmyadmin
index 8c2a6117b..5bfc88af8 100644
--- a/tools/headers/phpmyadmin
+++ b/tools/headers/phpmyadmin
@@ -1,4 +1,4 @@
- __ __ ___ ___ __ _
+ο»Ώ __ __ ___ ___ __ _
____ / /_ ____ / |/ /_ __/ | ____/ /___ ___ (_)___
/ __ \/ __ \/ __ \/ /|_/ / / / / /| |/ __ / __ `__ \/ / __ \
/ /_/ / / / / /_/ / / / / /_/ / ___ / /_/ / / / / / / / / / /
diff --git a/tools/headers/prx-add-ips b/tools/headers/prx-add-ips
index ea035b532..707c586c2 100644
--- a/tools/headers/prx-add-ips
+++ b/tools/headers/prx-add-ips
@@ -1,4 +1,4 @@
- ____ ___ __ __ ________
+ο»Ώ ____ ___ __ __ ________
/ __ \_________ _ ______ ___ ____ _ __ / | ____/ /___/ / / _/ __ \_____
/ /_/ / ___/ __ \| |/_/ __ `__ \/ __ \| |/_/ / /| |/ __ / __ /_____ / // /_/ / ___/
/ ____/ / / /_/ /> / / / / / /_/ /> < / ___ / /_/ / /_/ /_____// // ____(__ )
diff --git a/tools/headers/pve-privilege-converter b/tools/headers/pve-privilege-converter
index 47d0c3657..621e03056 100644
--- a/tools/headers/pve-privilege-converter
+++ b/tools/headers/pve-privilege-converter
@@ -1,4 +1,4 @@
- ____ _ ________ ____ _ _ __ ______ __
+ο»Ώ ____ _ ________ ____ _ _ __ ______ __
/ __ \ | / / ____/ / __ \_____(_) __(_) /__ ____ ____ / ____/___ ____ _ _____ _____/ /____ _____
/ /_/ / | / / __/______/ /_/ / ___/ / | / / / / _ \/ __ `/ _ \______/ / / __ \/ __ \ | / / _ \/ ___/ __/ _ \/ ___/
/ ____/| |/ / /__/_____/ ____/ / / /| |/ / / / __/ /_/ / __/_____/ /___/ /_/ / / / / |/ / __/ / / /_/ __/ /
diff --git a/tools/headers/qbittorrent-exporter b/tools/headers/qbittorrent-exporter
deleted file mode 100644
index 07677b261..000000000
--- a/tools/headers/qbittorrent-exporter
+++ /dev/null
@@ -1,6 +0,0 @@
- __ _ __ __ __ __
- ____ _/ /_ (_) /_/ /_____ _____________ ____ / /_ ___ _ ______ ____ _____/ /____ _____
- / __ `/ __ \/ / __/ __/ __ \/ ___/ ___/ _ \/ __ \/ __/_____/ _ \| |/_/ __ \/ __ \/ ___/ __/ _ \/ ___/
-/ /_/ / /_/ / / /_/ /_/ /_/ / / / / / __/ / / / /_/_____/ __/> /_/ / /_/ / / / /_/ __/ /
-\__, /_.___/_/\__/\__/\____/_/ /_/ \___/_/ /_/\__/ \___/_/|_/ .___/\____/_/ \__/\___/_/
- /_/ /_/
diff --git a/tools/headers/saltminion b/tools/headers/saltminion
index 4cab51ed3..a624df074 100644
--- a/tools/headers/saltminion
+++ b/tools/headers/saltminion
@@ -1,4 +1,4 @@
- ____ _ _
+ο»Ώ ____ _ _
_________ _/ / /_____ ___ (_)___ (_)___ ____
/ ___/ __ `/ / __/ __ `__ \/ / __ \/ / __ \/ __ \
(__ ) /_/ / / /_/ / / / / / / / / / / /_/ / / / /
diff --git a/tools/pve/add-iptag.sh b/tools/pve/add-iptag.sh
index 742a07a02..3872fc7b8 100644
--- a/tools/pve/add-iptag.sh
+++ b/tools/pve/add-iptag.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (Canbiz) && Desert_Gamer
# License: MIT
diff --git a/tools/pve/clean-lxcs.sh b/tools/pve/clean-lxcs.sh
index e6d06c229..a835263bb 100644
--- a/tools/pve/clean-lxcs.sh
+++ b/tools/pve/clean-lxcs.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk (CanbiZ)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/clean.sh b/tools/pve/clean.sh
index 87d3c9af8..4c9bf24f5 100644
--- a/tools/pve/clean.sh
+++ b/tools/pve/clean.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/container-restore-from-backup.sh b/tools/pve/container-restore-from-backup.sh
index 5588dd179..d69e1c442 100644
--- a/tools/pve/container-restore-from-backup.sh
+++ b/tools/pve/container-restore-from-backup.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -30,12 +30,12 @@ done
clear
function header_info {
cat <<"EOF"
- __ __ ___ _ __ __
- / / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_
- / /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/
- / __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_
-/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/
- RESTORE FROM BACKUP
+ __ __ ___ _ __ __
+ / / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_
+ / /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/
+ / __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_
+/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/
+ RESTORE FROM BACKUP
EOF
}
diff --git a/tools/pve/core-restore-from-backup.sh b/tools/pve/core-restore-from-backup.sh
index ee21b3ffc..422898594 100644
--- a/tools/pve/core-restore-from-backup.sh
+++ b/tools/pve/core-restore-from-backup.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -30,12 +30,12 @@ done
clear
function header_info {
cat <<"EOF"
- __ __ ___ _ __ __ ______
- / / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / ____/___ ________
+ __ __ ___ _ __ __ ______
+ / / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / ____/___ ________
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / __ \/ ___/ _ \
/ __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /___/ /_/ / / / __/
-/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/ \____/\____/_/ \___/
- RESTORE FROM BACKUP
+/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/ \____/\____/_/ \___/
+ RESTORE FROM BACKUP
EOF
}
diff --git a/tools/pve/execute.sh b/tools/pve/execute.sh
index fc19be981..24b03ff3a 100644
--- a/tools/pve/execute.sh
+++ b/tools/pve/execute.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: jeroenzwart
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -10,10 +10,10 @@ function header_info() {
cat <<"EOF"
______ __ __ _ ________
/ ____/ _____ _______ __/ /____ / / | |/ / ____/
- / __/ | |/_/ _ \/ ___/ / / / __/ _ \ / / | / /
- / /____> __/ /__/ /_/ / /_/ __/ / /___/ / /___
-/_____/_/|_|\___/\___/\__,_/\__/\___/ /_____/_/|_\____/
-
+ / __/ | |/_/ _ \/ ___/ / / / __/ _ \ / / | / /
+ / /____> __/ /__/ /_/ / /_/ __/ / /___/ / /___
+/_____/_/|_|\___/\___/\__,_/\__/\___/ /_____/_/|_\____/
+
EOF
}
set -eEuo pipefail
diff --git a/tools/pve/frigate-support.sh b/tools/pve/frigate-support.sh
index dd7e1edf3..c48e03bf2 100644
--- a/tools/pve/frigate-support.sh
+++ b/tools/pve/frigate-support.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/tools/pve/host-backup.sh b/tools/pve/host-backup.sh
index 8662c706c..8e963169b 100644
--- a/tools/pve/host-backup.sh
+++ b/tools/pve/host-backup.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/tools/pve/kernel-clean.sh b/tools/pve/kernel-clean.sh
index 796c363a7..17f5c9127 100644
--- a/tools/pve/kernel-clean.sh
+++ b/tools/pve/kernel-clean.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/lxc-delete.sh b/tools/pve/lxc-delete.sh
index 85487cd2c..d7248099d 100644
--- a/tools/pve/lxc-delete.sh
+++ b/tools/pve/lxc-delete.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/lxc-update.sh b/tools/pve/lxc-update.sh
index e4ed5ffb5..1366c028d 100644
--- a/tools/pve/lxc-update.sh
+++ b/tools/pve/lxc-update.sh
@@ -1,18 +1,18 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: BvdBerg01
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
function header_info {
clear
cat <<"EOF"
- __ _ ________ __ __ __ __
- / / | |/ / ____/ / / / /___ ____/ /___ _/ /____
+ __ _ ________ __ __ __ __
+ / / | |/ / ____/ / / / /___ ____/ /___ _/ /____
/ / | / / / / / / __ \/ __ / __ `/ __/ _ \
/ /___/ / /___ / /_/ / /_/ / /_/ / /_/ / /_/ __/
-/_____/_/|_\____/ \____/ .___/\__,_/\__,_/\__/\___/
- /_/
+/_____/_/|_\____/ \____/ .___/\__,_/\__,_/\__/\___/
+ /_/
EOF
}
@@ -149,7 +149,7 @@ fi
header_info
if(whiptail --backtitle "Proxmox VE Helper Scripts" --title "LXC Container Update" --yesno "Do you want to create a backup from your container?" 10 58); then
-
+
STORAGES=$(awk '/^(\S+):/ {storage=$2} /content.*backup/ {print storage}' /etc/pve/storage.cfg)
if [ -z "$STORAGES" ]; then
@@ -200,5 +200,5 @@ else
else
msg_error "Restored LXC from backup failed"
fi
-
-fi
\ No newline at end of file
+
+fi
diff --git a/tools/pve/oci-deploy.sh b/tools/pve/oci-deploy.sh
new file mode 100644
index 000000000..97e3f476f
--- /dev/null
+++ b/tools/pve/oci-deploy.sh
@@ -0,0 +1,352 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2021-2026 community-scripts ORG
+# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
+# Source: https://www.proxmox.com/
+
+function header_info {
+ clear
+ cat <<"EOF"
+ ____ ________ ______ __ _
+ / __ \/ ____/ / / ____/___ ____ / /_____ _(_)___ ___ _____
+ / / / / / / / / / / __ \/ __ \/ __/ __ `/ / __ \/ _ \/ ___/
+/ /_/ / /___/ / / /___/ /_/ / / / / /_/ /_/ / / / / / __/ /
+\____/\____/_/ \____/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/
+
+EOF
+}
+
+YW=$(echo "\033[33m")
+GN=$(echo "\033[1;92m")
+RD=$(echo "\033[01;31m")
+BL=$(echo "\033[36m")
+CL=$(echo "\033[m")
+CM="${GN}βοΈ${CL}"
+CROSS="${RD}βοΈ${CL}"
+INFO="${BL}βΉοΈ${CL}"
+
+APP="OCI-Container"
+
+header_info
+
+function msg_info() {
+ local msg="$1"
+ echo -e "${INFO} ${YW}${msg}...${CL}"
+}
+
+function msg_ok() {
+ local msg="$1"
+ echo -e "${CM} ${GN}${msg}${CL}"
+}
+
+function msg_error() {
+ local msg="$1"
+ echo -e "${CROSS} ${RD}${msg}${CL}"
+}
+
+# Check Proxmox version
+if ! command -v pveversion &>/dev/null; then
+ msg_error "This script must be run on Proxmox VE"
+ exit 1
+fi
+
+PVE_VER=$(pveversion | grep -oP 'pve-manager/\K[0-9.]+' | cut -d. -f1,2)
+MAJOR=$(echo "$PVE_VER" | cut -d. -f1)
+MINOR=$(echo "$PVE_VER" | cut -d. -f2)
+
+if [[ "$MAJOR" -lt 9 ]] || { [[ "$MAJOR" -eq 9 ]] && [[ "$MINOR" -lt 1 ]]; }; then
+ msg_error "Proxmox VE 9.1+ required (current: $PVE_VER)"
+ exit 1
+fi
+
+msg_ok "Proxmox VE $PVE_VER detected"
+
+# Parse OCI image
+parse_image() {
+ local input="$1"
+ if [[ "$input" =~ ^([^/]+\.[^/]+)/ ]]; then
+ echo "$input"
+ elif [[ "$input" =~ / ]]; then
+ echo "docker.io/$input"
+ else
+ echo "docker.io/library/$input"
+ fi
+}
+
+# Interactive image selection
+if [[ -z "${OCI_IMAGE:-}" ]]; then
+ echo ""
+ echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e "${BL}Select OCI Image:${CL}"
+ echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e " ${BL}1)${CL} nginx:alpine - Lightweight web server"
+ echo -e " ${BL}2)${CL} postgres:16-alpine - PostgreSQL database"
+ echo -e " ${BL}3)${CL} redis:alpine - Redis cache"
+ echo -e " ${BL}4)${CL} mariadb:latest - MariaDB database"
+ echo -e " ${BL}5)${CL} ghcr.io/linkwarden/linkwarden:latest"
+ echo -e " ${BL}6)${CL} Custom image"
+ echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo ""
+
+ read -r -p "Select option (1-6): " IMAGE_CHOICE
+
+ case $IMAGE_CHOICE in
+ 1) OCI_IMAGE="nginx:alpine" ;;
+ 2) OCI_IMAGE="postgres:16-alpine" ;;
+ 3) OCI_IMAGE="redis:alpine" ;;
+ 4) OCI_IMAGE="mariadb:latest" ;;
+ 5) OCI_IMAGE="ghcr.io/linkwarden/linkwarden:latest" ;;
+ 6)
+ read -r -p "Enter OCI image (e.g., ghcr.io/user/repo:tag): " OCI_IMAGE
+ [[ -z "$OCI_IMAGE" ]] && {
+ msg_error "No image specified"
+ exit 1
+ }
+ ;;
+ *)
+ msg_error "Invalid choice"
+ exit 1
+ ;;
+ esac
+fi
+
+FULL_IMAGE=$(parse_image "$OCI_IMAGE")
+msg_ok "Selected: $FULL_IMAGE"
+
+# Derive container name
+if [[ -z "${CT_NAME:-}" ]]; then
+ DEFAULT_NAME=$(echo "$OCI_IMAGE" | sed 's|.*/||; s/:.*//; s/[^a-zA-Z0-9-]/-/g' | cut -c1-60)
+ read -r -p "Container name [${DEFAULT_NAME}]: " CT_NAME
+ CT_NAME=${CT_NAME:-$DEFAULT_NAME}
+fi
+
+# Get next VMID
+if [[ -z "${VMID:-}" ]]; then
+ NEXT_ID=$(pvesh get /cluster/nextid)
+ read -r -p "Container ID [${NEXT_ID}]: " VMID
+ VMID=${VMID:-$NEXT_ID}
+fi
+
+# Resources
+if [[ -z "${CORES:-}" ]]; then
+ read -r -p "CPU cores [2]: " CORES
+ CORES=${CORES:-2}
+fi
+
+if [[ -z "${MEMORY:-}" ]]; then
+ read -r -p "Memory in MB [2048]: " MEMORY
+ MEMORY=${MEMORY:-2048}
+fi
+
+if [[ -z "${DISK:-}" ]]; then
+ read -r -p "Disk size in GB [8]: " DISK
+ DISK=${DISK:-8}
+fi
+
+# Storage
+if [[ -z "${STORAGE:-}" ]]; then
+ AVAIL_STORAGE=$(pvesm status | awk '/^local-(zfs|lvm)/ {print $1; exit}')
+ [[ -z "$AVAIL_STORAGE" ]] && AVAIL_STORAGE="local"
+ read -r -p "Storage [${AVAIL_STORAGE}]: " STORAGE
+ STORAGE=${STORAGE:-$AVAIL_STORAGE}
+fi
+
+# Network
+if [[ -z "${BRIDGE:-}" ]]; then
+ read -r -p "Network bridge [vmbr0]: " BRIDGE
+ BRIDGE=${BRIDGE:-vmbr0}
+fi
+
+if [[ -z "${IP_MODE:-}" ]]; then
+ read -r -p "IP mode (dhcp/static) [dhcp]: " IP_MODE
+ IP_MODE=${IP_MODE:-dhcp}
+fi
+
+if [[ "$IP_MODE" == "static" ]]; then
+ read -r -p "Static IP (CIDR, e.g., 192.168.1.100/24): " STATIC_IP
+ read -r -p "Gateway IP: " GATEWAY
+fi
+
+# Environment variables
+declare -a ENV_VARS=()
+
+case "$OCI_IMAGE" in
+postgres* | postgresql*)
+ echo ""
+ msg_info "PostgreSQL requires environment variables"
+ read -r -p "PostgreSQL password: " -s PG_PASS
+ echo ""
+ ENV_VARS+=("POSTGRES_PASSWORD=$PG_PASS")
+
+ read -r -p "Create database (optional): " PG_DB
+ [[ -n "$PG_DB" ]] && ENV_VARS+=("POSTGRES_DB=$PG_DB")
+
+ read -r -p "PostgreSQL user (optional): " PG_USER
+ [[ -n "$PG_USER" ]] && ENV_VARS+=("POSTGRES_USER=$PG_USER")
+ ;;
+
+mariadb* | mysql*)
+ echo ""
+ msg_info "MariaDB/MySQL requires environment variables"
+ read -r -p "Root password: " -s MYSQL_PASS
+ echo ""
+ ENV_VARS+=("MYSQL_ROOT_PASSWORD=$MYSQL_PASS")
+
+ read -r -p "Create database (optional): " MYSQL_DB
+ [[ -n "$MYSQL_DB" ]] && ENV_VARS+=("MYSQL_DATABASE=$MYSQL_DB")
+
+ read -r -p "Create user (optional): " MYSQL_USER
+ if [[ -n "$MYSQL_USER" ]]; then
+ ENV_VARS+=("MYSQL_USER=$MYSQL_USER")
+ read -r -p "User password: " -s MYSQL_USER_PASS
+ echo ""
+ ENV_VARS+=("MYSQL_PASSWORD=$MYSQL_USER_PASS")
+ fi
+ ;;
+
+*linkwarden*)
+ echo ""
+ msg_info "Linkwarden configuration"
+ read -r -p "NEXTAUTH_SECRET (press Enter to generate): " NEXTAUTH_SECRET
+ if [[ -z "$NEXTAUTH_SECRET" ]]; then
+ NEXTAUTH_SECRET=$(openssl rand -base64 32)
+ fi
+ ENV_VARS+=("NEXTAUTH_SECRET=$NEXTAUTH_SECRET")
+
+ read -r -p "NEXTAUTH_URL [http://localhost:3000]: " NEXTAUTH_URL
+ NEXTAUTH_URL=${NEXTAUTH_URL:-http://localhost:3000}
+ ENV_VARS+=("NEXTAUTH_URL=$NEXTAUTH_URL")
+
+ read -r -p "DATABASE_URL (PostgreSQL connection string): " DATABASE_URL
+ [[ -n "$DATABASE_URL" ]] && ENV_VARS+=("DATABASE_URL=$DATABASE_URL")
+ ;;
+esac
+
+# Additional env vars
+read -r -p "Add custom environment variables? (y/N): " ADD_ENV
+if [[ "${ADD_ENV,,}" =~ ^(y|yes)$ ]]; then
+ while true; do
+ read -r -p "Enter KEY=VALUE (or press Enter to finish): " CUSTOM_ENV
+ [[ -z "$CUSTOM_ENV" ]] && break
+ ENV_VARS+=("$CUSTOM_ENV")
+ done
+fi
+
+# Privileged mode
+read -r -p "Run as privileged container? (y/N): " PRIV_MODE
+if [[ "${PRIV_MODE,,}" =~ ^(y|yes)$ ]]; then
+ UNPRIVILEGED="0"
+else
+ UNPRIVILEGED="1"
+fi
+
+# Auto-start
+read -r -p "Start container after creation? (Y/n): " AUTO_START
+if [[ "${AUTO_START,,}" =~ ^(n|no)$ ]]; then
+ START_AFTER="no"
+else
+ START_AFTER="yes"
+fi
+
+# Summary
+echo ""
+echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+echo -e "${BL}Container Configuration Summary:${CL}"
+echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+echo -e " Image: $FULL_IMAGE"
+echo -e " ID: $VMID"
+echo -e " Name: $CT_NAME"
+echo -e " CPUs: $CORES"
+echo -e " Memory: ${MEMORY}MB"
+echo -e " Disk: ${DISK}GB"
+echo -e " Storage: $STORAGE"
+echo -e " Network: $BRIDGE ($IP_MODE)"
+[[ ${#ENV_VARS[@]} -gt 0 ]] && echo -e " Env vars: ${#ENV_VARS[@]} configured"
+echo -e "${YW}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+echo ""
+
+read -r -p "Proceed with creation? (Y/n): " CONFIRM
+if [[ "${CONFIRM,,}" =~ ^(n|no)$ ]]; then
+ msg_error "Cancelled by user"
+ exit 0
+fi
+
+# Create container
+msg_info "Creating container $VMID"
+
+# Build pct create command
+PCT_CMD="pct create $VMID"
+PCT_CMD+=" --hostname $CT_NAME"
+PCT_CMD+=" --cores $CORES"
+PCT_CMD+=" --memory $MEMORY"
+PCT_CMD+=" --rootfs ${STORAGE}:${DISK},oci=${FULL_IMAGE}"
+PCT_CMD+=" --unprivileged $UNPRIVILEGED"
+
+if [[ "$IP_MODE" == "static" && -n "$STATIC_IP" ]]; then
+ PCT_CMD+=" --net0 name=eth0,bridge=$BRIDGE,ip=$STATIC_IP"
+ [[ -n "$GATEWAY" ]] && PCT_CMD+=",gw=$GATEWAY"
+else
+ PCT_CMD+=" --net0 name=eth0,bridge=$BRIDGE,ip=dhcp"
+fi
+
+if eval "$PCT_CMD" 2>&1; then
+ msg_ok "Container created"
+else
+ msg_error "Failed to create container"
+ exit 1
+fi
+
+# Set environment variables
+if [[ ${#ENV_VARS[@]} -gt 0 ]]; then
+ msg_info "Configuring environment variables"
+ for env_var in "${ENV_VARS[@]}"; do
+ if pct set "$VMID" -env "$env_var" &>/dev/null; then
+ :
+ else
+ msg_error "Failed to set: $env_var"
+ fi
+ done
+ msg_ok "Environment variables configured (${#ENV_VARS[@]} variables)"
+fi
+
+# Start container
+if [[ "$START_AFTER" == "yes" ]]; then
+ msg_info "Starting container"
+ if pct start "$VMID" 2>&1; then
+ msg_ok "Container started"
+
+ # Wait for network
+ sleep 3
+ CT_IP=$(pct exec "$VMID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "N/A")
+
+ echo ""
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e "${BL}Container Information:${CL}"
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e " ID: ${GN}$VMID${CL}"
+ echo -e " Name: ${GN}$CT_NAME${CL}"
+ echo -e " Image: ${GN}$FULL_IMAGE${CL}"
+ echo -e " IP: ${GN}$CT_IP${CL}"
+ echo -e " Status: ${GN}Running${CL}"
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo ""
+ echo -e "${INFO} ${YW}Access console:${CL} pct console $VMID"
+ echo -e "${INFO} ${YW}View logs:${CL} pct logs $VMID"
+ echo ""
+ else
+ msg_error "Failed to start container"
+ fi
+else
+ echo ""
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e "${BL}Container Information:${CL}"
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo -e " ID: ${GN}$VMID${CL}"
+ echo -e " Name: ${GN}$CT_NAME${CL}"
+ echo -e " Image: ${GN}$FULL_IMAGE${CL}"
+ echo -e " Status: ${YW}Stopped${CL}"
+ echo -e "${GN}βββββββββββββββββββββββββββββββββββββββββββββ${CL}"
+ echo ""
+ echo -e "${INFO} ${YW}Start with:${CL} pct start $VMID"
+ echo ""
+fi
diff --git a/tools/pve/post-pve-install.sh b/tools/pve/post-pve-install.sh
index 42df5d77a..26b330ce3 100644
--- a/tools/pve/post-pve-install.sh
+++ b/tools/pve/post-pve-install.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteckster | MickLesk (CanbiZ)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/pve-privilege-converter.sh b/tools/pve/pve-privilege-converter.sh
index 0519baba5..a8b1cb0a8 100644
--- a/tools/pve/pve-privilege-converter.sh
+++ b/tools/pve/pve-privilege-converter.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# Adapted from onethree7 (https://github.com/onethree7/proxmox-lxc-privilege-converter)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/pyenv.sh b/tools/pve/pyenv.sh
index 78deaeaad..21376de1c 100644
--- a/tools/pve/pyenv.sh
+++ b/tools/pve/pyenv.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -60,7 +60,7 @@ git clone https://github.com/pyenv/pyenv.git ~/.pyenv &>/dev/null
set +e
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
-echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >> ~/.bashrc
+echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >> ~/.bashrc
msg_ok "Installed pyenv"
. ~/.bashrc
set -e
@@ -110,7 +110,7 @@ pip3 install --pre esphome &>/dev/null
cat </srv/esphome/start.sh
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -149,8 +149,8 @@ libgirepository1.0-dev \
libpango1.0-dev \
libgif-dev \
g++ &>/dev/null
-python3 -m pip install wheel
-pip3 install --upgrade pip
+python3 -m pip install wheel
+pip3 install --upgrade pip
pip install python-matter-server[server]
msg_ok "Installed Matter Server"
echo -e "Start server > python -m matter_server.server"
diff --git a/tools/pve/switch_from_VED_to_VE.sh b/tools/pve/switch_from_VED_to_VE.sh
index 251b3caf1..ca8038a69 100644
--- a/tools/pve/switch_from_VED_to_VE.sh
+++ b/tools/pve/switch_from_VED_to_VE.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/update-apps.sh b/tools/pve/update-apps.sh
index f07e5c03d..b4977e130 100644
--- a/tools/pve/update-apps.sh
+++ b/tools/pve/update-apps.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: BvdBerg01 | Co-Author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
diff --git a/tools/pve/usb-passthrough.sh b/tools/pve/usb-passthrough.sh
index fa26f0100..c5205961b 100644
--- a/tools/pve/usb-passthrough.sh
+++ b/tools/pve/usb-passthrough.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
diff --git a/vm/allstarlink-vm.sh b/vm/allstarlink-vm.sh
index 0dc1bf3c0..d0f04f78c 100644
--- a/vm/allstarlink-vm.sh
+++ b/vm/allstarlink-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: Don Locke (DonLocke)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/AllStarLink
@@ -494,4 +494,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started AllStarLink VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/archlinux-vm.sh b/vm/archlinux-vm.sh
index fa28e60b0..43511ee33 100644
--- a/vm/archlinux-vm.sh
+++ b/vm/archlinux-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -525,4 +525,4 @@ if [ "$START_VM" == "yes" ]; then
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/debian-13-vm.sh b/vm/debian-13-vm.sh
index 97ca4de15..8ed60d80b 100644
--- a/vm/debian-13-vm.sh
+++ b/vm/debian-13-vm.sh
@@ -298,9 +298,9 @@ function advanced_settings() {
exit-script
fi
- if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 debian --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VM_NAME ]; then
- HN="unifi-os-server"
+ HN="debian"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
HN=$(echo ${VM_NAME,,} | tr -d ' ')
diff --git a/vm/debian-vm-test-helper.sh b/vm/debian-vm-test-helper.sh
index d831aab46..a8a80a3b7 100644
--- a/vm/debian-vm-test-helper.sh
+++ b/vm/debian-vm-test-helper.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -402,5 +402,5 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Debian 12 VM"
fi
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo "More Info at https://github.com/community-scripts/ProxmoxVED/discussions/836"
diff --git a/vm/debian-vm.sh b/vm/debian-vm.sh
index f88a59501..38d7f432f 100644
--- a/vm/debian-vm.sh
+++ b/vm/debian-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -376,5 +376,5 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Debian 12 VM"
fi
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
msg_custom "More Info at https://github.com/community-scripts/ProxmoxVED/discussions/836"
diff --git a/vm/docker-vm-debug.sh b/vm/docker-vm-debug.sh
index 6da5ec333..b571287d7 100644
--- a/vm/docker-vm-debug.sh
+++ b/vm/docker-vm-debug.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: thost96 (thost96) | Co-Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -914,4 +914,4 @@ if [ "$USE_CLOUD_INIT" = "yes" ]; then
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/docker-vm.sh b/vm/docker-vm.sh
index d8ab522fb..013988b0c 100644
--- a/vm/docker-vm.sh
+++ b/vm/docker-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: thost96 (thost96) | Co-Author: michelroegl-brunner | Refactored: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE
@@ -777,4 +777,4 @@ if [ "$USE_CLOUD_INIT" = "yes" ]; then
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/docker-vm.sh.bak b/vm/docker-vm.sh.bak
index 36f7177ff..9e700b9fa 100644
--- a/vm/docker-vm.sh.bak
+++ b/vm/docker-vm.sh.bak
@@ -4,7 +4,7 @@
# PVE 8: direct inject via virt-customize
# PVE 9: Cloud-Init (user-data via local:snippets)
#
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: thost96 (thost96) | Co-Author: michelroegl-brunner
# Refactor (q35 + PVE9 cloud-init + Robustheit): MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -629,7 +629,7 @@ if [[ "$START_VM" == "yes" ]]; then
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
# ---- Hinweise/Debug (Cloud-Init) --------------------------------------------
# In der VM prΓΌfen:
diff --git a/vm/haos-vm.sh b/vm/haos-vm.sh
index ea7ff30d0..df256948c 100644
--- a/vm/haos-vm.sh
+++ b/vm/haos-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -548,4 +548,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Home Assistant OS VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/headers/allstarlink-vm b/vm/headers/allstarlink-vm
new file mode 100644
index 000000000..ea38cad61
--- /dev/null
+++ b/vm/headers/allstarlink-vm
@@ -0,0 +1,6 @@
+ο»Ώ __ __ _ ______
+ ____/ /__ / /_ (_)___ _____ < /__ \_ ______ ___
+ / __ / _ \/ __ \/ / __ `/ __ \/ /__/ / | / / __ `__ \
+/ /_/ / __/ /_/ / / /_/ / / / / // __/| |/ / / / / / /
+\__,_/\___/_.___/_/\__,_/_/ /_/_//____/|___/_/ /_/ /_/
+
diff --git a/vm/headers/archlinux-vm b/vm/headers/archlinux-vm
new file mode 100644
index 000000000..21f6e897f
--- /dev/null
+++ b/vm/headers/archlinux-vm
@@ -0,0 +1,6 @@
+ο»Ώ __ ___
+ ____ ___________/ /_ / (_)___ __ ___ __ _ ______ ___
+ / __ `/ ___/ ___/ __ \______/ / / __ \/ / / / |/_/____| | / / __ `__ \
+/ /_/ / / / /__/ / / /_____/ / / / / / /_/ /> /_/ /__/ / /_/ / /_/ / /_/ /
+\__/\__,_/_/ /_/ /_/_/|_|\___/\__, / /_/ /_/\___/_/|_|\__/\___/_/\____/\__,_/\__,_/
+ /____/
diff --git a/vm/headers/openwrt b/vm/headers/openwrt
new file mode 100644
index 000000000..ab601af5b
--- /dev/null
+++ b/vm/headers/openwrt
@@ -0,0 +1,6 @@
+ο»Ώ __
+ ____ ____ ___ ____ _ _______/ /_ _ ______ ___
+ / __ \/ __ \/ _ \/ __ \ | /| / / ___/ __/____| | / / __ `__ \
+/ /_/ / /_/ / __/ / / / |/ |/ / / / /_/_____/ |/ / / / / / /
+\____/ .___/\___/_/ /_/|__/|__/_/ \__/ |___/_/ /_/ /_/
+ /_/
diff --git a/vm/headers/opnsense-vm b/vm/headers/opnsense-vm
new file mode 100644
index 000000000..b847609ce
--- /dev/null
+++ b/vm/headers/opnsense-vm
@@ -0,0 +1,6 @@
+ο»Ώ
+ ____ ____ ____ ________ ____ ________ _ ______ ___
+ / __ \/ __ \/ __ \/ ___/ _ \/ __ \/ ___/ _ \_____| | / / __ `__ \
+/ /_/ / /_/ / / / (__ ) __/ / / (__ ) __/_____/ |/ / / / / / /
+\____/ .___/_/ /_/____/\___/_/ /_/____/\___/ |___/_/ /_/ /_/
+ /_/
diff --git a/vm/headers/owncloud-vm b/vm/headers/owncloud-vm
new file mode 100644
index 000000000..53238b539
--- /dev/null
+++ b/vm/headers/owncloud-vm
@@ -0,0 +1,6 @@
+ο»Ώ __ __ __ __
+ / /___ ___________ / /_____ __ __ ____ _ ______ _____/ /___ __ ______/ / _ ______ ___
+ / __/ / / / ___/ __ \/ //_/ _ \/ / / /_____/ __ \ | /| / / __ \/ ___/ / __ \/ / / / __ /____| | / / __ `__ \
+/ /_/ /_/ / / / / / / ,< / __/ /_/ /_____/ /_/ / |/ |/ / / / / /__/ / /_/ / /_/ / /_/ /_____/ |/ / / / / / /
+\__/\__,_/_/ /_/ /_/_/|_|\___/\__, / \____/|__/|__/_/ /_/\___/_/\____/\__,_/\__,_/ |___/_/ /_/ /_/
+ /____/
diff --git a/vm/headers/pimox-haos-vm b/vm/headers/pimox-haos-vm
new file mode 100644
index 000000000..1f055db3d
--- /dev/null
+++ b/vm/headers/pimox-haos-vm
@@ -0,0 +1,6 @@
+ο»Ώ _ __
+ ____ (_)___ ___ ____ _ __ / /_ ____ _____ _____ _ ______ ___
+ / __ \/ / __ `__ \/ __ \| |/_/_____/ __ \/ __ `/ __ \/ ___/____| | / / __ `__ \
+ / /_/ / / / / / / / /_/ />
-
+
GitHub
@@ -346,4 +346,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Mikrotik RouterOS CHR VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/nextcloud-vm.sh b/vm/nextcloud-vm.sh
index 083534c3f..93ea21f4f 100644
--- a/vm/nextcloud-vm.sh
+++ b/vm/nextcloud-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -481,4 +481,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started $NAME"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/openwrt.sh b/vm/openwrt.sh
index d5c8a0f38..c6e097014 100644
--- a/vm/openwrt.sh
+++ b/vm/openwrt.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Jon Spriggs (jontheniceguy)
# License: MIT
diff --git a/vm/opnsense-vm.sh b/vm/opnsense-vm.sh
index 156fb913d..131382929 100644
--- a/vm/opnsense-vm.sh
+++ b/vm/opnsense-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -686,7 +686,7 @@ sleep 10
send_line_to_vm "0"
msg_ok "Started OPNsense VM"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
if [ "$IP_ADDR" != "" ]; then
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP_ADDR}${CL}"
diff --git a/vm/owncloud-vm.sh b/vm/owncloud-vm.sh
index 7db765ad3..23769982d 100644
--- a/vm/owncloud-vm.sh
+++ b/vm/owncloud-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -482,4 +482,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started $NAME"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/pimox-haos-vm.sh b/vm/pimox-haos-vm.sh
index b925ab442..4ee0d0c9e 100644
--- a/vm/pimox-haos-vm.sh
+++ b/vm/pimox-haos-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -9,16 +9,16 @@ source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-sc
function header_info {
cat <<"EOF"
- ____ _ __ ___
- / __ \(_) |/ /___ _ __
- / /_/ / / /|_/ / __ \| |/_/
- / ____/ / / / / /_/ /> <
+ ____ _ __ ___
+ / __ \(_) |/ /___ _ __
+ / /_/ / / /|_/ / __ \| |/_/
+ / ____/ / / / / /_/ /> <
__ __ /_/_ /_/_/ /_/\____/_/|_| __ ____ _____
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / __ \/ ___/
- / /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / /\__ \
- / __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /_/ /___/ /
-/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/ \____//____/
-
+ / /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / /\__ \
+ / __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /_/ /___/ /
+/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/ \____//____/
+
EOF
}
clear
@@ -357,7 +357,7 @@ DESCRIPTION=$(
-
+
GitHub
@@ -382,4 +382,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Home Assistant OS VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/ubuntu2204-vm.sh b/vm/ubuntu2204-vm.sh
index 2946da3e7..14a89b939 100644
--- a/vm/ubuntu2204-vm.sh
+++ b/vm/ubuntu2204-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -522,6 +522,6 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Ubuntu 22.04 VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "Setup Cloud-Init before starting \n
More info at https://github.com/community-scripts/ProxmoxVE/discussions/272 \n"
diff --git a/vm/ubuntu2404-vm.sh b/vm/ubuntu2404-vm.sh
index 04afdc82a..7bcfc4137 100644
--- a/vm/ubuntu2404-vm.sh
+++ b/vm/ubuntu2404-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 tteck
+# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -524,6 +524,6 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Ubuntu 24.04 VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "Setup Cloud-Init before starting \n
More info at https://github.com/community-scripts/ProxmoxVE/discussions/272 \n"
diff --git a/vm/ubuntu2410-vm.sh b/vm/ubuntu2410-vm.sh
index 071062fc4..46d900c6e 100644
--- a/vm/ubuntu2410-vm.sh
+++ b/vm/ubuntu2410-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -658,6 +658,6 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started $APP"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
echo -e "Setup Cloud-Init before starting \n
More info at https://github.com/community-scripts/ProxmoxVE/discussions/272 \n"
diff --git a/vm/umbrel-os-vm.sh b/vm/umbrel-os-vm.sh
index bdaca5ca2..6e7e4b25f 100644
--- a/vm/umbrel-os-vm.sh
+++ b/vm/umbrel-os-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -527,4 +527,4 @@ if [ "$START_VM" == "yes" ]; then
msg_ok "Started Umbrel OS VM"
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
diff --git a/vm/unifi-os-server-vm.sh b/vm/unifi-os-server-vm.sh
index 5e356349b..14fd08382 100644
--- a/vm/unifi-os-server-vm.sh
+++ b/vm/unifi-os-server-vm.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-# Copyright (c) 2021-2025 community-scripts ORG
+# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -104,7 +104,76 @@ function cleanup_vmid() {
if qm status $VMID &>/dev/null; then
qm stop $VMID &>/dev/null
qm destroy $VMID &>/dev/null
- fi
+}
+
+function send_line_to_vm() {
+ local line="$1"
+ for ((i = 0; i < ${#line}; i++)); do
+ character=${line:i:1}
+ case $character in
+ " ") character="spc" ;;
+ "-") character="minus" ;;
+ "=") character="equal" ;;
+ ",") character="comma" ;;
+ ".") character="dot" ;;
+ "/") character="slash" ;;
+ "'") character="apostrophe" ;;
+ ";") character="semicolon" ;;
+ '\') character="backslash" ;;
+ '\`') character="grave_accent" ;;
+ "[") character="bracket_left" ;;
+ "]") character="bracket_right" ;;
+ "_") character="shift-minus" ;;
+ "+") character="shift-equal" ;;
+ "?") character="shift-slash" ;;
+ "<") character="shift-comma" ;;
+ ">") character="shift-dot" ;;
+ '"') character="shift-apostrophe" ;;
+ ":") character="shift-semicolon" ;;
+ "|") character="shift-backslash" ;;
+ "~") character="shift-grave_accent" ;;
+ "{") character="shift-bracket_left" ;;
+ "}") character="shift-bracket_right" ;;
+ "A") character="shift-a" ;;
+ "B") character="shift-b" ;;
+ "C") character="shift-c" ;;
+ "D") character="shift-d" ;;
+ "E") character="shift-e" ;;
+ "F") character="shift-f" ;;
+ "G") character="shift-g" ;;
+ "H") character="shift-h" ;;
+ "I") character="shift-i" ;;
+ "J") character="shift-j" ;;
+ "K") character="shift-k" ;;
+ "L") character="shift-l" ;;
+ "M") character="shift-m" ;;
+ "N") character="shift-n" ;;
+ "O") character="shift-o" ;;
+ "P") character="shift-p" ;;
+ "Q") character="shift-q" ;;
+ "R") character="shift-r" ;;
+ "S") character="shift-s" ;;
+ "T") character="shift-t" ;;
+ "U") character="shift-u" ;;
+ "V") character="shift-v" ;;
+ "W") character="shift-w" ;;
+ "X") character="shift-x" ;;
+ "Y") character="shift-y" ;;
+ "Z") character="shift-z" ;;
+ "!") character="shift-1" ;;
+ "@") character="shift-2" ;;
+ "#") character="shift-3" ;;
+ '$') character="shift-4" ;;
+ "%") character="shift-5" ;;
+ "^") character="shift-6" ;;
+ "&") character="shift-7" ;;
+ "*") character="shift-8" ;;
+ "(") character="shift-9" ;;
+ ")") character="shift-0" ;;
+ esac
+ qm sendkey $VMID "$character"
+ done
+ qm sendkey $VMID ret
}
function cleanup() {
@@ -143,7 +212,6 @@ function check_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.
@@ -160,8 +228,6 @@ pve_check() {
msg_error "Supported: Proxmox VE version 8.0 β 8.9"
exit 1
fi
- return 0
- fi
# Check for Proxmox VE 9.x: allow 9.0β9.1
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
@@ -171,8 +237,6 @@ pve_check() {
msg_error "Supported: Proxmox VE version 9.0 β 9.1"
exit 1
fi
- return 0
- fi
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
@@ -187,7 +251,6 @@ function arch_check() {
echo -e "Exiting..."
sleep 2
exit
- fi
}
function ssh_check() {
@@ -200,7 +263,6 @@ function ssh_check() {
exit
fi
fi
- fi
}
function exit-script() {
@@ -229,23 +291,22 @@ function select_os() {
OS_DISPLAY="Ubuntu 24.04 LTS"
;;
esac
- echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
+ #echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
else
exit-script
- fi
}
function select_cloud_init() {
# UniFi OS Server ALWAYS requires Cloud-Init for automated installation
USE_CLOUD_INIT="yes"
- echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (required for UniFi OS)${CL}"
+ #echo -e "${CLOUD}${BOLD}${DGN}Cloud-Init: ${BGN}yes (required for UniFi OS)${CL}"
}
function get_image_url() {
local arch=$(dpkg --print-architecture)
case $OS_TYPE in
debian)
- # Always use generic (Cloud-Init) variant for UniFi OS
+ # Always use &1 1>&2 2>&3); then
if [ -z "$VMID" ]; then
@@ -321,22 +382,22 @@ function advanced_settings() {
fi
done
- if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
+ MACH="q35"
+ if MACH_RESULT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \
"q35" "Q35 (Modern, PCIe, UEFI)" ON \
"i440fx" "i440fx (Legacy)" OFF \
3>&1 1>&2 2>&3); then
- if [ "$MACH" = "q35" ]; then
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
- FORMAT=""
- MACHINE=" -machine q35"
- else
- echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
- FORMAT=",efitype=4m"
- MACHINE=""
- fi
+ MACH="$MACH_RESULT"
else
exit-script
- fi
+ if [ "$MACH" = "q35" ]; then
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
+ FORMAT=""
+ MACHINE=" -machine q35"
+ else
+ echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
+ FORMAT=",efitype=4m"
+ MACHINE=""
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 ' ')
@@ -351,7 +412,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
"0" "None (Default)" ON \
@@ -366,7 +426,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 unifi-os-server --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VM_NAME ]; then
@@ -378,7 +437,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 10 58 2 \
"Host" "Host (Faster, recommended)" ON \
@@ -396,7 +454,6 @@ function advanced_settings() {
esac
else
exit-script
- fi
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $CORE_COUNT ]; then
@@ -407,7 +464,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $RAM_SIZE ]; then
@@ -418,7 +474,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $BRG ]; then
@@ -429,7 +484,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $MAC1 ]; then
@@ -441,7 +495,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VLAN1 ]; then
@@ -454,7 +507,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $MTU1 ]; then
@@ -467,7 +519,6 @@ function advanced_settings() {
fi
else
exit-script
- fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
@@ -475,7 +526,6 @@ function advanced_settings() {
else
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
START_VM="no"
- fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Unifi OS VM?" --no-button Do-Over 10 58); then
echo -e "${CREATING}${BOLD}${DGN}Creating a Unifi OS VM using the above advanced settings${CL}"
@@ -483,7 +533,6 @@ function advanced_settings() {
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
advanced_settings
- fi
}
function start_script() {
@@ -495,25 +544,50 @@ function start_script() {
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
advanced_settings
- fi
}
check_root
arch_check
pve_check
ssh_check
+
start_script
post_to_api_vm
+msg_info "Checking system resources"
+SYSTEM_RAM_GB=$(grep MemTotal /proc/meminfo | awk '{printf "%.0f", $2 / 1024 / 1024}')
+SYSTEM_SWAP_GB=$(grep SwapTotal /proc/meminfo | awk '{printf "%.0f", $2 / 1024 / 1024}')
+SYSTEM_FREE_DISK_GB=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//')
+if [[ ${SYSTEM_RAM_GB} -lt 4 ]]; then
+ msg_error "Warning: Less than 4GB RAM detected (${SYSTEM_RAM_GB}GB). Install may be slow."
+ sleep 3
+fi
+if [[ ${SYSTEM_FREE_DISK_GB} -lt 10 ]]; then
+ msg_error "Warning: Less than 10GB free disk detected. Install may fail."
+ sleep 3
+fi
+msg_ok "System resources: ${SYSTEM_RAM_GB}GB RAM, ${SYSTEM_FREE_DISK_GB}GB free disk"
+
+if command -v ufw &>/dev/null; then
+ if ufw status verbose | grep -q "Status: active"; then
+ msg_info "Setting up firewall rules for UniFi OS Server ports"
+ ufw allow 11443/tcp 2>/dev/null
+ ufw allow 8080/tcp 2>/dev/null
+ ufw allow 3478/tcp 2>/dev/null
+ ufw allow 3478/udp 2>/dev/null
+ msg_ok "Firewall rules configured"
+fi
+
msg_info "Validating Storage"
+STORAGE_MENU=()
+MSG_MAX_LENGTH=0
while read -r line; do
TAG=$(echo $line | awk '{print $1}')
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
- FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
+ FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f 2>/dev/null || echo "N/A" | awk '{printf( "%9sB", $6)}')
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
- if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
+ if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-0} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
- fi
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
@@ -588,96 +662,17 @@ echo -en "\e[1A\e[0K"
FILE=$(basename $URL)
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
-# --- Inject UniFi Installer via Cloud-Init ---
-msg_info "Preparing ${OS_DISPLAY} Cloud Image for UniFi OS"
+msg_ok "Downloaded ${OS_DISPLAY} Cloud Image"
-# Install virt-customize if not available
-if ! command -v virt-customize &>/dev/null; then
+# Expand root partition to use full disk space
+msg_info "Expanding disk image to ${DISK_SIZE}"
+
+# Install virt-resize if not available
+if ! command -v virt-resize &>/dev/null; then
apt-get -qq update >/dev/null
apt-get -qq install libguestfs-tools -y >/dev/null
fi
-# Create UniFi OS installation script and inject it into the image
-virt-customize -a "${FILE}" --run-command "cat > /root/install-unifi-os.sh << 'INSTALLSCRIPT'
-#!/bin/bash
-set -x
-exec > /var/log/unifi-install.log 2>&1
-
-echo \"=== UniFi OS Installation Started at \$(date) ===\"
-
-# Wait for cloud-init to complete
-if command -v cloud-init >/dev/null 2>&1; then
- echo \"Waiting for cloud-init to complete...\"
- cloud-init status --wait 2>/dev/null || true
-fi
-
-# Install required packages
-echo \"Installing required packages...\"
-export DEBIAN_FRONTEND=noninteractive
-apt-get update
-apt-get install -y curl wget ca-certificates podman uidmap slirp4netns iptables
-
-# Configure Podman
-echo \"Configuring Podman...\"
-loginctl enable-linger root
-
-# Download UniFi OS Server
-echo \"Downloading UniFi OS Server ${UOS_VERSION}...\"
-cd /root
-curl -fsSL '${UOS_URL}' -o unifi-installer.bin
-chmod +x unifi-installer.bin
-
-# Install UniFi OS Server
-echo \"Installing UniFi OS Server (this takes 3-5 minutes)...\"
-./unifi-installer.bin install
-
-echo \"Waiting for services to start...\"
-sleep 15
-
-# Start UniFi OS Server
-if systemctl list-unit-files | grep -q unifi-os-server; then
- echo \"Starting UniFi OS Server service...\"
- systemctl enable unifi-os-server
- systemctl start unifi-os-server
- sleep 10
-
- if systemctl is-active --quiet unifi-os-server; then
- echo \"SUCCESS: UniFi OS Server is running\"
- else
- echo \"WARNING: Checking service status...\"
- systemctl status unifi-os-server --no-pager
- fi
-fi
-
-touch /root/.unifi-installed
-echo \"=== Installation completed at \$(date) ===\"
-INSTALLSCRIPT" >/dev/null 2>&1
-
-virt-customize -a "${FILE}" --chmod 0755:/root/install-unifi-os.sh >/dev/null 2>&1
-
-# Create systemd service for first-boot installation
-virt-customize -a "${FILE}" --run-command "cat > /etc/systemd/system/unifi-firstboot.service << 'SVCFILE'
-[Unit]
-Description=UniFi OS First Boot Installation
-After=cloud-init.service network-online.target
-Wants=network-online.target
-ConditionPathExists=!/root/.unifi-installed
-
-[Service]
-Type=oneshot
-ExecStart=/root/install-unifi-os.sh
-RemainAfterExit=yes
-
-[Install]
-WantedBy=multi-user.target
-SVCFILE" >/dev/null 2>&1
-
-virt-customize -a "${FILE}" --run-command "systemctl enable unifi-firstboot.service" >/dev/null 2>&1
-
-msg_ok "Prepared ${OS_DISPLAY} image with UniFi OS installer"
-
-# Expand root partition to use full disk space
-msg_info "Expanding disk image to ${DISK_SIZE}"
qemu-img create -f qcow2 expanded.qcow2 ${DISK_SIZE} >/dev/null 2>&1
# Detect partition device (sda1 for Ubuntu, vda1 for Debian)
@@ -712,21 +707,10 @@ qm set "$VMID" \
qm resize "$VMID" scsi0 "$DISK_SIZE" >/dev/null
qm set "$VMID" --agent enabled=1 >/dev/null
-# Add Cloud-Init drive (standard Cloud-Init, no custom user-data)
+# Add Cloud-Init drive
msg_info "Configuring Cloud-Init"
setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes" >/dev/null 2>&1
-msg_ok "Cloud-Init configured (UniFi OS installs via systemd service on first boot)"
-
-# Display credentials immediately so user can login
-if [ -n "$CLOUDINIT_CRED_FILE" ] && [ -f "$CLOUDINIT_CRED_FILE" ]; then
- echo ""
- echo -e "${INFO}${BOLD}${GN}Cloud-Init Credentials (save these now!):${CL}"
- echo -e "${TAB}${DGN}User: ${BGN}${CLOUDINIT_USER:-root}${CL}"
- echo -e "${TAB}${DGN}Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}"
- echo -e "${TAB}${RD}β οΈ UniFi OS installation runs automatically on first boot${CL}"
- echo -e "${TAB}${INFO}Monitor: ${BL}tail -f /var/log/unifi-install.log${CL}"
- echo ""
-fi
+msg_ok "Cloud-Init configured"
DESCRIPTION=$(
cat <> /etc/fstab"
+ sleep 1
+ msg_ok "Swap file created (size based on available disk space)"
+
+ # Step 2: Download UniFi OS Server installer
+ msg_info "Downloading UniFi OS Server ${UOS_VERSION}"
+ send_line_to_vm "cd /opt"
+ sleep 1
+ send_line_to_vm "wget -q ${UOS_URL} -O unifi-os-server.bin"
+ sleep 60
+ send_line_to_vm "chmod +x unifi-os-server.bin"
+ sleep 2
+ msg_ok "Downloaded UniFi OS Server installer"
+
+ # Step 3: Install UniFi OS Server (with auto-yes)
+ msg_info "Installing UniFi OS Server (this takes 3-5 minutes)"
+ send_line_to_vm "echo y | ./unifi-os-server.bin"
+ sleep 300
+ msg_ok "UniFi OS Server installed"
+
+ # Step 4: Start Guest Agent for IP detection
+ msg_info "Starting QEMU Guest Agent"
+ send_line_to_vm "systemctl start qemu-guest-agent"
+ sleep 3
+ msg_ok "Guest Agent started"
+
+ # Logout from VM console
+ send_line_to_vm "exit"
+ sleep 2
+
+ # Get IP from outside via Guest Agent
+ msg_info "Detecting VM IP address"
VM_IP=""
for i in {1..30}; do
- VM_IP=$(qm guest cmd $VMID network-get-interfaces 2>/dev/null | jq -r '.[1]["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | grep -v "127.0.0.1" | head -1 || echo "")
-
+ VM_IP=$(qm guest cmd $VMID network-get-interfaces 2>/dev/null | jq -r '.[] | select(.name != "lo") | .["ip-addresses"][]? | select(.["ip-address-type"] == "ipv4") | .["ip-address"]' 2>/dev/null | head -1 || echo "")
if [ -n "$VM_IP" ]; then
- msg_ok "VM IP Address detected: ${VM_IP}"
break
fi
- sleep 2
+ sleep 1
done
if [ -n "$VM_IP" ]; then
- msg_info "Waiting for UniFi OS installation (via Cloud-Init, takes 5-8 minutes)"
-
- WAIT_COUNT=0
- MAX_WAIT=600 # 10 minutes max for Cloud-Init installation
- PORT_OPEN=0
- LAST_MSG_TIME=0
-
- while [ $WAIT_COUNT -lt $MAX_WAIT ]; do
- if timeout 2 bash -c ">/dev/tcp/${VM_IP}/11443" 2>/dev/null; then
- PORT_OPEN=1
- msg_ok "UniFi OS Server is ready!"
- break
- fi
-
- sleep 10
- WAIT_COUNT=$((WAIT_COUNT + 10))
-
- # Update message every 30 seconds
- if [ $((WAIT_COUNT - LAST_MSG_TIME)) -ge 30 ]; then
- echo -e "${BFR}${TAB}${YW}${HOLD}Installation in progress... ${WAIT_COUNT}s elapsed${CL}"
- echo -e "${TAB}${INFO}${YW}Monitor: ${BL}ssh ${CLOUDINIT_USER:-root}@${VM_IP} 'tail -f /var/log/unifi-install.log'${CL}"
- LAST_MSG_TIME=$WAIT_COUNT
- fi
- done
-
- if [ $PORT_OPEN -eq 1 ]; then
- echo -e "\n${TAB}${GATEWAY}${BOLD}${GN}β UniFi OS Server is ready!${CL}"
- echo -e "${TAB}${GATEWAY}${BOLD}${GN}β Access at: ${BGN}https://${VM_IP}:11443${CL}\n"
- else
- msg_ok "VM is running, UniFi OS installation in progress"
- echo -e "${TAB}${INFO}${YW}Installation runs via systemd service on first boot${CL}"
- echo -e "${TAB}${INFO}${YW}This takes 5-8 minutes${CL}"
- if [ "$USE_CLOUD_INIT" = "yes" ]; then
- echo -e "${TAB}${INFO}${YW}SSH: ${BL}ssh ${CLOUDINIT_USER:-root}@${VM_IP}${CL}"
- echo -e "${TAB}${INFO}${YW}Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}"
- echo -e "${TAB}${INFO}${YW}Monitor: ${BL}tail -f /var/log/unifi-install.log${CL}"
- fi
- echo -e "${TAB}${INFO}${YW}UniFi OS will be at: ${BGN}https://${VM_IP}:11443${CL}"
- fi
+ msg_ok "VM IP Address: ${VM_IP}"
else
- msg_ok "VM is running (ID: ${VMID})"
- echo -e "${TAB}${INFO}${YW}Could not auto-detect IP address${CL}"
- echo -e "${TAB}${INFO}${YW}Use Proxmox Console to login with Cloud-Init credentials${CL}"
- echo -e "${TAB}${INFO}${YW}User: ${BGN}${CLOUDINIT_USER:-root}${CL} / Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}"
- echo -e "${TAB}${INFO}${YW}Monitor installation: ${BL}tail -f /var/log/unifi-install.log${CL}"
- fi
+ msg_info "Could not detect IP - check VM console"
+
+ echo ""
+ echo -e "${TAB}${GATEWAY}${BOLD}${GN}β UniFi OS Server installation complete!${CL}"
+ if [ -n "$VM_IP" ]; then
+ echo -e "${TAB}${GATEWAY}${BOLD}${GN}β Access at: ${BGN}https://${VM_IP}:11443${CL}"
+ else
+ echo -e "${TAB}${INFO}${YW}Access via: ${BGN}https://:11443${CL}"
+ echo -e "${TAB}${INFO}${DGN}Console login - User: ${BGN}root${CL} / Password: ${BGN}${CLOUDINIT_PASSWORD}${CL}"
+ echo -e "${TAB}${INFO}${YW}Note: UniFi OS may take 1-2 more minutes to fully start${CL}"
+ echo ""
fi
post_update_to_api "done" "none"
-msg_ok "Completed Successfully!\n"
+msg_ok "Completed successfully!\n"
+
+