Compare commits

..

6 Commits

Author SHA1 Message Date
CanbiZ (MickLesk)
d84770e215 chore(ct,tools): sync Source headers with install/ and add Github links to addon scripts 2026-02-24 14:36:19 +01:00
CanbiZ (MickLesk)
8deb4401b1 revert: restore misc/build.func and misc/core.func to main state
These error-handler fixes belong to fix/error-handler-recovery, not to
this sources-only branch.
2026-02-24 14:30:07 +01:00
CanbiZ (MickLesk)
b1edd80a96 chore(install): add Github source links to all fetch_and_deploy scripts
77 additional install scripts had fetch_and_deploy_gh_release calls but
no GitHub link in the Source header. Merged the primary app repo into
the Source header as:
  # Source: https://website.com/ | Github: https://github.com/OWNER/REPO

Where multiple fetch_and_deploy calls existed (app + dependency), the
primary app repo was selected:
- ersatztv: ErsatzTV/ErsatzTV (not ffmpeg)
- firefly: firefly-iii/firefly-iii (not data-importer)
- komga: gotson/komga (not kepubify dep)
- sabnzbd: sabnzbd/sabnzbd (not par2cmdline-turbo dep)
- signoz: SigNoz/signoz (not otel-collector)
- tunarr: chrisbenincasa/tunarr (not ffmpeg dep)

Also fixed cosmos-install.sh double https:// in Source URL.

Skipped: autocaliweb (source already on codeberg, GitHub repos are deps only)
2026-02-24 14:28:45 +01:00
CanbiZ (MickLesk)
da422b1036 chore(install): add Github source links to all setup_nodejs scripts
52 install scripts had a project website in '# Source:' but no GitHub
link. Merged the GitHub repo URL into the Source header as:
  # Source: https://website.com/ | Github: https://github.com/OWNER/REPO

Repos sourced from fetch_and_deploy_gh_release calls, get_latest_github_release
calls, or known project repos for npm/pip installed apps.

Two scripts (fumadocs, pve-scripts-local) had no Source line at all —
added one. Shinobi skipped (GitLab-only, no GitHub repo).
2026-02-24 14:21:43 +01:00
CanbiZ (MickLesk)
7bb14b4d22 Update build.func 2026-02-24 14:03:09 +01:00
CanbiZ (MickLesk)
75c0b1bfc9 fix(error-handler): prevent silent() from re-enabling error handling during recovery
Root cause: silent() (core.func) unconditionally calls set -Eeuo pipefail
and trap 'error_handler' ERR after every command. When build_container()
intentionally disables error handling for its recovery section, any
intermediate call through silent()/ re-enables it. This causes the
grep/sed pipeline for missing_cmd extraction to trigger error_handler
(grep returns exit code 1 on no match + pipefail = fatal).

Fixes:
1. silent(): Save errexit state before disabling, only restore if it was
   active. Callers that intentionally disabled error handling (e.g.
   build_container recovery) are no longer silently re-enabled.

2. build.func: Add || true to missing_cmd grep pipeline as defense-in-depth
   against pipeline failure propagation.

3. build.func: Add explicit set +Eeuo pipefail / trap - ERR after
   post_update_to_api() call, before error classification grep/sed section.

4. build.func: Remove stale global combined_log variable from variables()
   that used a different path format (/tmp/install-SESSION-combined.log)
   than the actual local variable (/tmp/NSAPP-CTID-SESSION.log). The global
   was never written to and caused confusion when error_handler displayed it.
2026-02-24 13:51:27 +01:00
191 changed files with 2450 additions and 6412 deletions

250
.github/changelogs/2026/02.md generated vendored
View File

@@ -1,253 +1,3 @@
## 2026-02-28
### 🚀 Updated Scripts
- Update Reactive Resume install script with useful .env information for reverse proxy setup [@Mazianni](https://github.com/Mazianni) ([#12401](https://github.com/community-scripts/ProxmoxVE/pull/12401))
- #### 🐞 Bug Fixes
- gramps-web: install addons (FilterRules) for relationship diagram [@MickLesk](https://github.com/MickLesk) ([#12387](https://github.com/community-scripts/ProxmoxVE/pull/12387))
- [Fix] Immich: Change `sed` command to fully replace line in postgresql.conf [@vhsdream](https://github.com/vhsdream) ([#12429](https://github.com/community-scripts/ProxmoxVE/pull/12429))
- [FIX] Immich: fix Openvino memory leak during OCR; improve HW-accelerated ML performance [@vhsdream](https://github.com/vhsdream) ([#12426](https://github.com/community-scripts/ProxmoxVE/pull/12426))
- Fix default tag for ioBroker LXC install [@josefglatz](https://github.com/josefglatz) ([#12423](https://github.com/community-scripts/ProxmoxVE/pull/12423))
- Ombi: Add database.json [@hraphael](https://github.com/hraphael) ([#12412](https://github.com/community-scripts/ProxmoxVE/pull/12412))
- Dawarich: add missing build deps and handle seed failure [@MickLesk](https://github.com/MickLesk) ([#12410](https://github.com/community-scripts/ProxmoxVE/pull/12410))
- pangolin: increase hdd to 10G [@MickLesk](https://github.com/MickLesk) ([#12409](https://github.com/community-scripts/ProxmoxVE/pull/12409))
- #### ✨ New Features
- BookLore: add additional JVM flags [@vhsdream](https://github.com/vhsdream) ([#12421](https://github.com/community-scripts/ProxmoxVE/pull/12421))
### 🗑️ Deleted Scripts
- Delete Palmr [@vhsdream](https://github.com/vhsdream) ([#12399](https://github.com/community-scripts/ProxmoxVE/pull/12399))
### 💾 Core
- #### 🐞 Bug Fixes
- core: read from /dev/tty in all interactive prompts | fix empty or cropped logs due build process [@MickLesk](https://github.com/MickLesk) ([#12406](https://github.com/community-scripts/ProxmoxVE/pull/12406))
## 2026-02-27
### 🆕 New Scripts
- Strapi ([#12320](https://github.com/community-scripts/ProxmoxVE/pull/12320))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- TrueNAS VM: filter out new nightlies with MASTER [@juronja](https://github.com/juronja) ([#12355](https://github.com/community-scripts/ProxmoxVE/pull/12355))
### 💾 Core
- #### ✨ New Features
- core: graceful fallback for apt-get update failures [@MickLesk](https://github.com/MickLesk) ([#12386](https://github.com/community-scripts/ProxmoxVE/pull/12386))
- core: Improve error outputs across core functions [@MickLesk](https://github.com/MickLesk) ([#12378](https://github.com/community-scripts/ProxmoxVE/pull/12378))
## 2026-02-26
### 🆕 New Scripts
- Kima-Hub ([#12319](https://github.com/community-scripts/ProxmoxVE/pull/12319))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- tools.func: update glx alternatives / nvidia alternative if nvidia glx are missing [@MickLesk](https://github.com/MickLesk) ([#12372](https://github.com/community-scripts/ProxmoxVE/pull/12372))
- hotfix: overseer version [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12366](https://github.com/community-scripts/ProxmoxVE/pull/12366))
- #### ✨ New Features
- Add ffmpeg for booklore (ffprobe) [@MickLesk](https://github.com/MickLesk) ([#12371](https://github.com/community-scripts/ProxmoxVE/pull/12371))
- [QOL] Immich: add warning regarding library compilation time [@vhsdream](https://github.com/vhsdream) ([#12345](https://github.com/community-scripts/ProxmoxVE/pull/12345))
### 🧰 Tools
- #### 🐞 Bug Fixes
- Improves adguardhome-sync addon when running on alpine LXCs [@Darkangeel-hd](https://github.com/Darkangeel-hd) ([#12362](https://github.com/community-scripts/ProxmoxVE/pull/12362))
- #### ✨ New Features
- Add Alpine support and improve Tailscale install [@MickLesk](https://github.com/MickLesk) ([#12370](https://github.com/community-scripts/ProxmoxVE/pull/12370))
### 📚 Documentation
- fix wrong link on contributions README.md [@Darkangeel-hd](https://github.com/Darkangeel-hd) ([#12363](https://github.com/community-scripts/ProxmoxVE/pull/12363))
### 📂 Github
- github: add workflow to autom. close unauthorized new-script PRs [@MickLesk](https://github.com/MickLesk) ([#12356](https://github.com/community-scripts/ProxmoxVE/pull/12356))
## 2026-02-25
### 🆕 New Scripts
- Zerobyte ([#12321](https://github.com/community-scripts/ProxmoxVE/pull/12321))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: overseer migration [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12340](https://github.com/community-scripts/ProxmoxVE/pull/12340))
- add: vikunja: daemon reload [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12323](https://github.com/community-scripts/ProxmoxVE/pull/12323))
- opnsense-VM: Use ip link to verify bridge existence [@MickLesk](https://github.com/MickLesk) ([#12329](https://github.com/community-scripts/ProxmoxVE/pull/12329))
- wger: Use $http_host for proxy Host header [@MickLesk](https://github.com/MickLesk) ([#12327](https://github.com/community-scripts/ProxmoxVE/pull/12327))
- Passbolt: Update Nginx config `client_max_body_size` [@tremor021](https://github.com/tremor021) ([#12313](https://github.com/community-scripts/ProxmoxVE/pull/12313))
- Zammad: configure Elasticsearch before zammad start [@MickLesk](https://github.com/MickLesk) ([#12308](https://github.com/community-scripts/ProxmoxVE/pull/12308))
- #### 🔧 Refactor
- OpenProject: Various fixes [@tremor021](https://github.com/tremor021) ([#12246](https://github.com/community-scripts/ProxmoxVE/pull/12246))
### 💾 Core
- #### 🐞 Bug Fixes
- Fix detection of ssh keys [@1-tempest](https://github.com/1-tempest) ([#12230](https://github.com/community-scripts/ProxmoxVE/pull/12230))
- #### ✨ New Features
- tools.func: Improve GitHub/Codeberg API error handling and error output [@MickLesk](https://github.com/MickLesk) ([#12330](https://github.com/community-scripts/ProxmoxVE/pull/12330))
- #### 🔧 Refactor
- core: remove duplicate traps, consolidate error handling and harden signal traps [@MickLesk](https://github.com/MickLesk) ([#12316](https://github.com/community-scripts/ProxmoxVE/pull/12316))
### 📂 Github
- github: improvements for node drift wf [@MickLesk](https://github.com/MickLesk) ([#12309](https://github.com/community-scripts/ProxmoxVE/pull/12309))
## 2026-02-24
### 🚀 Updated Scripts
- several scripts: add additional github link in source [@MickLesk](https://github.com/MickLesk) ([#12282](https://github.com/community-scripts/ProxmoxVE/pull/12282))
- adds further documentation during the installation script. [@d12rio](https://github.com/d12rio) ([#12248](https://github.com/community-scripts/ProxmoxVE/pull/12248))
- #### 🐞 Bug Fixes
- [Fix] PatchMon: remove VITE_API_URL from frontend env [@vhsdream](https://github.com/vhsdream) ([#12294](https://github.com/community-scripts/ProxmoxVE/pull/12294))
- fix(searxng): remove orphaned fi causing syntax error [@mark-jeffrey](https://github.com/mark-jeffrey) ([#12283](https://github.com/community-scripts/ProxmoxVE/pull/12283))
- Refactor n8n [@MickLesk](https://github.com/MickLesk) ([#12264](https://github.com/community-scripts/ProxmoxVE/pull/12264))
- Firefly: PHP bump [@tremor021](https://github.com/tremor021) ([#12247](https://github.com/community-scripts/ProxmoxVE/pull/12247))
- #### ✨ New Features
- Databasus: add mariadb path for mysql/mariadb backups | add mongodb database tools [@MickLesk](https://github.com/MickLesk) ([#12259](https://github.com/community-scripts/ProxmoxVE/pull/12259))
- make searxng updateable [@shtefko](https://github.com/shtefko) ([#12207](https://github.com/community-scripts/ProxmoxVE/pull/12207))
- #### 💥 Breaking Changes
- fix: wealthfolio for v3 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11765](https://github.com/community-scripts/ProxmoxVE/pull/11765))
- #### 🔧 Refactor
- bump various scripts from Node 22 to 24 [@MickLesk](https://github.com/MickLesk) ([#12265](https://github.com/community-scripts/ProxmoxVE/pull/12265))
### 💾 Core
- #### 🐞 Bug Fixes
- core: fix broken "command not found" after err_trap [@MickLesk](https://github.com/MickLesk) ([#12280](https://github.com/community-scripts/ProxmoxVE/pull/12280))
- #### ✨ New Features
- tools.func: add get_latest_gh_tag helper function [@MickLesk](https://github.com/MickLesk) ([#12261](https://github.com/community-scripts/ProxmoxVE/pull/12261))
### 🧰 Tools
- Arcane ([#12263](https://github.com/community-scripts/ProxmoxVE/pull/12263))
### 📂 Github
- github: add weekly Node.js version drift check workflow [@MickLesk](https://github.com/MickLesk) ([#12267](https://github.com/community-scripts/ProxmoxVE/pull/12267))
- add: workflow to close stale PRs [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12243](https://github.com/community-scripts/ProxmoxVE/pull/12243))
## 2026-02-23
### 🆕 New Scripts
- SeaweedFS ([#12220](https://github.com/community-scripts/ProxmoxVE/pull/12220))
- Sonobarr ([#12221](https://github.com/community-scripts/ProxmoxVE/pull/12221))
- SparkyFitness ([#12185](https://github.com/community-scripts/ProxmoxVE/pull/12185))
- Frigate v16.4 [@MickLesk](https://github.com/MickLesk) ([#11887](https://github.com/community-scripts/ProxmoxVE/pull/11887))
### 🚀 Updated Scripts
- #### ✨ New Features
- memos: unpin version due new release artifacts [@MickLesk](https://github.com/MickLesk) ([#12224](https://github.com/community-scripts/ProxmoxVE/pull/12224))
- core: Enhance signal handling, reported "status" and logs [@MickLesk](https://github.com/MickLesk) ([#12216](https://github.com/community-scripts/ProxmoxVE/pull/12216))
- #### 🔧 Refactor
- booklore v2: embed frontend, bump Java to 25, remove nginx [@MickLesk](https://github.com/MickLesk) ([#12223](https://github.com/community-scripts/ProxmoxVE/pull/12223))
### 🗑️ Deleted Scripts
- Remove: Huntarr (deprecated & Security) [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#12226](https://github.com/community-scripts/ProxmoxVE/pull/12226))
### 💾 Core
- #### 🔧 Refactor
- core: Improve error handling and logging for LXC builds [@MickLesk](https://github.com/MickLesk) ([#12208](https://github.com/community-scripts/ProxmoxVE/pull/12208))
### 🌐 Website
- #### 🐞 Bug Fixes
- calibre-web: update default credentials [@LaevaertK](https://github.com/LaevaertK) ([#12201](https://github.com/community-scripts/ProxmoxVE/pull/12201))
- #### 📝 Script Information
- chore: update Frigate documentation and website URLs [@JohnICB](https://github.com/JohnICB) ([#12218](https://github.com/community-scripts/ProxmoxVE/pull/12218))
## 2026-02-22
### 🆕 New Scripts
- Gramps-Web ([#12157](https://github.com/community-scripts/ProxmoxVE/pull/12157))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: Apache Guacamole - bump to Temurin JDK 17 to resolve Debian 13 (Trixie) install failure [@Copilot](https://github.com/Copilot) ([#12161](https://github.com/community-scripts/ProxmoxVE/pull/12161))
- Docker-VM: add error handling for virt-customize finalization [@MickLesk](https://github.com/MickLesk) ([#12127](https://github.com/community-scripts/ProxmoxVE/pull/12127))
- [Fix] Sure: add Sidekiq service [@vhsdream](https://github.com/vhsdream) ([#12186](https://github.com/community-scripts/ProxmoxVE/pull/12186))
- #### ✨ New Features
- Refactor & Bump to v2: Plex [@MickLesk](https://github.com/MickLesk) ([#12179](https://github.com/community-scripts/ProxmoxVE/pull/12179))
- #### 🔧 Refactor
- karakeep: bump to node 24 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12183](https://github.com/community-scripts/ProxmoxVE/pull/12183))
### 💾 Core
- #### ✨ New Features
- tools.func: add GitHub API rate-limit detection and GITHUB_TOKEN support [@MickLesk](https://github.com/MickLesk) ([#12176](https://github.com/community-scripts/ProxmoxVE/pull/12176))
### 🧰 Tools
- CR*NMASTER ([#12065](https://github.com/community-scripts/ProxmoxVE/pull/12065))
- #### 🔧 Refactor
- Update package management commands in clean-lxcs.sh [@heinemannj](https://github.com/heinemannj) ([#12166](https://github.com/community-scripts/ProxmoxVE/pull/12166))
### ❔ Uncategorized
- calibre-web: Update logo URL [@MickLesk](https://github.com/MickLesk) ([#12178](https://github.com/community-scripts/ProxmoxVE/pull/12178))
## 2026-02-21 ## 2026-02-21
### 🚀 Updated Scripts ### 🚀 Updated Scripts

View File

@@ -13,7 +13,7 @@ permissions:
jobs: jobs:
check-node-versions: check-node-versions:
if: github.repository == 'community-scripts/ProxmoxVE' if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: coolify-runner runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
@@ -110,94 +110,22 @@ jobs:
} }
# Extract Node major from engines.node in package.json # Extract Node major from engines.node in package.json
# Sets: ENGINES_NODE_RAW (raw string), ENGINES_MIN_MAJOR, ENGINES_IS_MINIMUM # Sets: ENGINES_NODE_RAW (raw string), ENGINES_MIN_MAJOR
extract_engines_node() { extract_engines_node() {
local content="$1" local content="$1"
ENGINES_NODE_RAW="" ENGINES_NODE_RAW=""
ENGINES_MIN_MAJOR="" ENGINES_MIN_MAJOR=""
ENGINES_IS_MINIMUM="false"
ENGINES_NODE_RAW=$(echo "$content" | jq -r '.engines.node // empty' 2>/dev/null || echo "") ENGINES_NODE_RAW=$(echo "$content" | jq -r '.engines.node // empty' 2>/dev/null || echo "")
if [[ -z "$ENGINES_NODE_RAW" ]]; then if [[ -z "$ENGINES_NODE_RAW" ]]; then
return return
fi fi
# Detect if constraint is a minimum (>=, ^) vs exact pinning
if [[ "$ENGINES_NODE_RAW" =~ ^(\>=|\^|\~) ]]; then
ENGINES_IS_MINIMUM="true"
fi
# Extract the first number (major) from the constraint # Extract the first number (major) from the constraint
# Handles: ">=24.13.1", "^22", ">=18.0.0", ">=18.15.0 <19 || ^20", etc. # Handles: ">=24.13.1", "^22", ">=18.0.0", ">=18.15.0 <19 || ^20", etc.
ENGINES_MIN_MAJOR=$(echo "$ENGINES_NODE_RAW" | grep -oP '\d+' | head -1 || echo "") ENGINES_MIN_MAJOR=$(echo "$ENGINES_NODE_RAW" | grep -oP '\d+' | head -1 || echo "")
} }
# Check if our_version satisfies an engines.node constraint
# Returns 0 if satisfied, 1 if not
# Usage: version_satisfies_engines "22" ">=18.0.0" "true"
version_satisfies_engines() {
local our="$1"
local min_major="$2"
local is_minimum="$3"
if [[ -z "$min_major" || -z "$our" ]]; then
return 1
fi
if [[ "$is_minimum" == "true" ]]; then
# >= or ^ constraint: our version must be >= min_major
if [[ "$our" -ge "$min_major" ]]; then
return 0
fi
fi
return 1
}
# Search for files in subdirectories via GitHub API tree
# Usage: find_repo_file "owner/repo" "branch" "filename" => sets REPLY to raw URL or empty
find_repo_file() {
local repo="$1"
local branch="$2"
local filename="$3"
REPLY=""
# Try root first (fast)
local root_url="https://raw.githubusercontent.com/${repo}/${branch}/${filename}"
if curl -sfI "$root_url" >/dev/null 2>&1; then
REPLY="$root_url"
return
fi
# Search via GitHub API tree (recursive)
local tree_url="https://api.github.com/repos/${repo}/git/trees/${branch}?recursive=1"
local tree_json
tree_json=$(curl -sf -H "Authorization: token $GH_TOKEN" "$tree_url" 2>/dev/null || echo "")
if [[ -z "$tree_json" ]]; then
return
fi
# Find first matching path (prefer shorter/root-level paths)
local match_path
match_path=$(echo "$tree_json" | jq -r --arg fn "$filename" \
'.tree[]? | select(.path | endswith("/" + $fn) or . == $fn) | .path' 2>/dev/null \
| sort | head -1 || echo "")
if [[ -n "$match_path" ]]; then
REPLY="https://raw.githubusercontent.com/${repo}/${branch}/${match_path}"
fi
}
# Extract Node major from .nvmrc or .node-version
# Sets: NVMRC_NODE_MAJOR
extract_nvmrc_node() {
local content="$1"
NVMRC_NODE_MAJOR=""
# .nvmrc/.node-version typically has: "v22.9.0", "22", "lts/iron", etc.
local ver
ver=$(echo "$content" | tr -d '[:space:]' | grep -oP '^v?\K[0-9]+' | head -1 || echo "")
NVMRC_NODE_MAJOR="$ver"
}
# Collect results # Collect results
declare -a issue_scripts=() declare -a issue_scripts=()
declare -a report_lines=() declare -a report_lines=()
@@ -214,12 +142,8 @@ jobs:
total=$((total + 1)) total=$((total + 1))
slug=$(basename "$script" | sed 's/-install\.sh$//') slug=$(basename "$script" | sed 's/-install\.sh$//')
# Extract Source URL (GitHub only) from the "# Source:" line # Extract Source URL (GitHub only)
# Supports both: source_url=$(head -20 "$script" | grep -oP '(?<=# Source: )https://github\.com/[^\s]+' | head -1 || echo "")
# # Source: https://github.com/owner/repo
# # Source: https://example.com | Github: https://github.com/owner/repo
# NOTE: Must filter for "# Source:" line first to avoid matching the License URL
source_url=$(head -20 "$script" | grep -i '# Source:' | grep -oP 'https://github\.com/[^\s|]+' | head -1 || echo "")
if [[ -z "$source_url" ]]; then if [[ -z "$source_url" ]]; then
report_lines+=("| \`$slug\` | — | — | — | — | ⏭️ No GitHub source |") report_lines+=("| \`$slug\` | — | — | — | — | ⏭️ No GitHub source |")
continue continue
@@ -243,23 +167,12 @@ jobs:
fi fi
fi fi
# Determine default branch via GitHub API (fast, single call) # Fetch upstream Dockerfile
detected_branch=""
api_default=$(curl -sf -H "Authorization: token $GH_TOKEN" \
"https://api.github.com/repos/${repo}" 2>/dev/null \
| jq -r '.default_branch // empty' 2>/dev/null || echo "")
if [[ -n "$api_default" ]]; then
detected_branch="$api_default"
else
detected_branch="main"
fi
# Fetch upstream Dockerfile (root + subdirectories)
df_content="" df_content=""
find_repo_file "$repo" "$detected_branch" "Dockerfile" for branch in main master dev; do
if [[ -n "$REPLY" ]]; then df_content=$(curl -sf "https://raw.githubusercontent.com/${repo}/${branch}/Dockerfile" 2>/dev/null || echo "")
df_content=$(curl -sf "$REPLY" 2>/dev/null || echo "") [[ -n "$df_content" ]] && break
fi done
DF_NODE_MAJOR="" DF_NODE_MAJOR=""
DF_SOURCE="" DF_SOURCE=""
@@ -267,35 +180,19 @@ jobs:
extract_dockerfile_node "$df_content" extract_dockerfile_node "$df_content"
fi fi
# Fetch upstream package.json (root + subdirectories) # Fetch upstream package.json
pkg_content="" pkg_content=""
find_repo_file "$repo" "$detected_branch" "package.json" for branch in main master dev; do
if [[ -n "$REPLY" ]]; then pkg_content=$(curl -sf "https://raw.githubusercontent.com/${repo}/${branch}/package.json" 2>/dev/null || echo "")
pkg_content=$(curl -sf "$REPLY" 2>/dev/null || echo "") [[ -n "$pkg_content" ]] && break
fi done
ENGINES_NODE_RAW="" ENGINES_NODE_RAW=""
ENGINES_MIN_MAJOR="" ENGINES_MIN_MAJOR=""
ENGINES_IS_MINIMUM="false"
if [[ -n "$pkg_content" ]]; then if [[ -n "$pkg_content" ]]; then
extract_engines_node "$pkg_content" extract_engines_node "$pkg_content"
fi fi
# Fallback: check .nvmrc or .node-version
NVMRC_NODE_MAJOR=""
if [[ -z "$DF_NODE_MAJOR" && -z "$ENGINES_MIN_MAJOR" ]]; then
for nvmfile in .nvmrc .node-version; do
find_repo_file "$repo" "$detected_branch" "$nvmfile"
if [[ -n "$REPLY" ]]; then
nvmrc_content=$(curl -sf "$REPLY" 2>/dev/null || echo "")
if [[ -n "$nvmrc_content" ]]; then
extract_nvmrc_node "$nvmrc_content"
[[ -n "$NVMRC_NODE_MAJOR" ]] && break
fi
fi
done
fi
# Determine upstream recommended major version # Determine upstream recommended major version
upstream_major="" upstream_major=""
upstream_hint="" upstream_hint=""
@@ -306,9 +203,6 @@ jobs:
elif [[ -n "$ENGINES_MIN_MAJOR" ]]; then elif [[ -n "$ENGINES_MIN_MAJOR" ]]; then
upstream_major="$ENGINES_MIN_MAJOR" upstream_major="$ENGINES_MIN_MAJOR"
upstream_hint="engines: $ENGINES_NODE_RAW" upstream_hint="engines: $ENGINES_NODE_RAW"
elif [[ -n "$NVMRC_NODE_MAJOR" ]]; then
upstream_major="$NVMRC_NODE_MAJOR"
upstream_hint=".nvmrc/.node-version"
fi fi
# Build display values # Build display values
@@ -320,23 +214,13 @@ jobs:
if [[ "$our_version" == "dynamic" ]]; then if [[ "$our_version" == "dynamic" ]]; then
status="🔄 Dynamic" status="🔄 Dynamic"
elif [[ "$our_version" == "unset" ]]; then elif [[ "$our_version" == "unset" ]]; then
if [[ -n "$upstream_major" ]]; then status="⚠️ NODE_VERSION not set"
status="⚠️ NODE_VERSION not set (upstream=$upstream_major via $upstream_hint)"
else
status="⚠️ NODE_VERSION not set (no upstream info found)"
fi
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo") issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
drift_count=$((drift_count + 1)) drift_count=$((drift_count + 1))
elif [[ -n "$upstream_major" && "$our_version" != "$upstream_major" ]]; then elif [[ -n "$upstream_major" && "$our_version" != "$upstream_major" ]]; then
# Check if engines.node is a minimum constraint that our version satisfies status="🔸 Drift → upstream=$upstream_major ($upstream_hint)"
if [[ -z "$DF_NODE_MAJOR" && "$ENGINES_IS_MINIMUM" == "true" ]] && \ issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
version_satisfies_engines "$our_version" "$ENGINES_MIN_MAJOR" "$ENGINES_IS_MINIMUM"; then drift_count=$((drift_count + 1))
status="✅ (engines: $ENGINES_NODE_RAW — ours: $our_version satisfies)"
else
status="🔸 Drift → upstream=$upstream_major ($upstream_hint)"
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
drift_count=$((drift_count + 1))
fi
fi fi
report_lines+=("| \`$slug\` | $our_version | $engines_display | $dockerfile_display | [$repo](https://github.com/$repo) | $status |") report_lines+=("| \`$slug\` | $our_version | $engines_display | $dockerfile_display | [$repo](https://github.com/$repo) | $status |")

View File

@@ -1,119 +0,0 @@
name: Close Unauthorized New Script PRs
on:
pull_request_target:
branches: ["main"]
types: [opened, labeled]
jobs:
check-new-script:
if: github.repository == 'community-scripts/ProxmoxVE'
runs-on: coolify-runner
permissions:
pull-requests: write
contents: read
steps:
- name: Close PR if unauthorized new script submission
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const prNumber = pr.number;
const author = pr.user.login;
const authorType = pr.user.type; // "User" or "Bot"
const owner = context.repo.owner;
const repo = context.repo.repo;
// --- Only act on PRs with the "new script" label ---
const labels = pr.labels.map(l => l.name);
if (!labels.includes("new script")) {
core.info(`PR #${prNumber} does not have "new script" label — skipping.`);
return;
}
// --- Allow our bots ---
const allowedBots = [
"push-app-to-main[bot]",
"push-app-to-main",
];
if (allowedBots.includes(author)) {
core.info(`PR #${prNumber} by allowed bot "${author}" — skipping.`);
return;
}
// --- Check if author is a member of the contributor team ---
const teamSlug = "contributor";
let isMember = false;
try {
const { status } = await github.rest.teams.getMembershipForUserInOrg({
org: owner,
team_slug: teamSlug,
username: author,
});
// status 200 means the user is a member (active or pending)
isMember = true;
} catch (error) {
if (error.status === 404) {
isMember = false;
} else {
core.warning(`Could not check team membership for ${author}: ${error.message}`);
// Fallback: check org membership
try {
await github.rest.orgs.checkMembershipForUser({
org: owner,
username: author,
});
isMember = true;
} catch {
isMember = false;
}
}
}
if (isMember) {
core.info(`PR #${prNumber} by contributor "${author}" — skipping.`);
return;
}
// --- Unauthorized: close the PR with a comment ---
core.info(`Closing PR #${prNumber} by "${author}" — not a contributor or allowed bot.`);
const comment = [
`👋 Hi @${author},`,
``,
`Thank you for your interest in contributing a new script!`,
``,
`However, **new scripts must first be submitted to our development repository** for testing and review before they can be merged here.`,
``,
`> 🛑 New scripts must be submitted to [**ProxmoxVED**](https://github.com/community-scripts/ProxmoxVED) for testing.`,
`> PRs without prior testing will be closed.`,
``,
`Please open your PR at **https://github.com/community-scripts/ProxmoxVED** instead.`,
`Once your script has been tested and approved there, it will be pushed to this repository automatically.`,
``,
`This PR will now be closed. Thank you for understanding! 🙏`,
].join("\n");
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: comment,
});
await github.rest.pulls.update({
owner,
repo,
pull_number: prNumber,
state: "closed",
});
// Add a label to indicate why it was closed
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: ["not a script issue"],
});

View File

@@ -1,255 +0,0 @@
name: Push JSON changes to PocketBase
on:
push:
branches:
- main
paths:
- "frontend/public/json/**"
jobs:
push-json:
runs-on: self-hosted
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed JSON files with slug
id: changed
run: |
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- frontend/public/json/ | grep '\.json$' || true)
with_slug=""
for f in $changed; do
[[ -f "$f" ]] || continue
jq -e '.slug' "$f" >/dev/null 2>&1 && with_slug="$with_slug $f"
done
with_slug=$(echo $with_slug | xargs -n1)
if [[ -z "$with_slug" ]]; then
echo "No app JSON files changed (or no files with slug)."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$with_slug" > changed_app_jsons.txt
echo "count=$(echo "$with_slug" | wc -w)" >> "$GITHUB_OUTPUT"
- name: Push to PocketBase
if: steps.changed.outputs.count != '0'
env:
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
run: |
node << 'ENDSCRIPT'
(async function() {
const fs = require('fs');
const https = require('https');
const http = require('http');
const url = require('url');
function request(fullUrl, opts) {
return new Promise(function(resolve, reject) {
const u = url.parse(fullUrl);
const isHttps = u.protocol === 'https:';
const body = opts.body;
const options = {
hostname: u.hostname,
port: u.port || (isHttps ? 443 : 80),
path: u.path,
method: opts.method || 'GET',
headers: opts.headers || {}
};
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
const lib = isHttps ? https : http;
const req = lib.request(options, function(res) {
let data = '';
res.on('data', function(chunk) { data += chunk; });
res.on('end', function() {
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
});
});
req.on('error', reject);
if (body) req.write(body);
req.end();
});
}
const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
const coll = process.env.POCKETBASE_COLLECTION;
const files = fs.readFileSync('changed_app_jsons.txt', 'utf8').trim().split(/\s+/).filter(Boolean);
const authUrl = apiBase + '/collections/users/auth-with-password';
console.log('Auth URL: ' + authUrl);
const authBody = JSON.stringify({
identity: process.env.POCKETBASE_ADMIN_EMAIL,
password: process.env.POCKETBASE_ADMIN_PASSWORD
});
const authRes = await request(authUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: authBody
});
if (!authRes.ok) {
throw new Error('Auth failed. Tried: ' + authUrl + ' - Verify POST to that URL with body {"identity":"...","password":"..."} works. Response: ' + authRes.body);
}
const token = JSON.parse(authRes.body).token;
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
let categoryIdToName = {};
try {
const metadata = JSON.parse(fs.readFileSync('frontend/public/json/metadata.json', 'utf8'));
(metadata.categories || []).forEach(function(cat) { categoryIdToName[cat.id] = cat.name; });
} catch (e) { console.warn('Could not load metadata.json:', e.message); }
let typeValueToId = {};
let categoryNameToPbId = {};
try {
const typesRes = await request(apiBase + '/collections/z_ref_script_types/records?perPage=500', { headers: { 'Authorization': token } });
if (typesRes.ok) {
const typesData = JSON.parse(typesRes.body);
(typesData.items || []).forEach(function(item) {
if (item.type != null) typeValueToId[item.type] = item.id;
if (item.name != null) typeValueToId[item.name] = item.id;
if (item.value != null) typeValueToId[item.value] = item.id;
});
}
} catch (e) { console.warn('Could not fetch z_ref_script_types:', e.message); }
try {
const catRes = await request(apiBase + '/collections/script_categories/records?perPage=500', { headers: { 'Authorization': token } });
if (catRes.ok) {
const catData = JSON.parse(catRes.body);
(catData.items || []).forEach(function(item) { if (item.name) categoryNameToPbId[item.name] = item.id; });
}
} catch (e) { console.warn('Could not fetch script_categories:', e.message); }
var noteTypeToId = {};
var installMethodTypeToId = {};
var osToId = {};
var osVersionToId = {};
try {
const res = await request(apiBase + '/collections/z_ref_note_types/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) noteTypeToId[item.type] = item.id; });
} catch (e) { console.warn('z_ref_note_types:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_install_method_types/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) installMethodTypeToId[item.type] = item.id; });
} catch (e) { console.warn('z_ref_install_method_types:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_os/records?perPage=500', { headers: { 'Authorization': token } });
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.os != null) osToId[item.os] = item.id; });
} catch (e) { console.warn('z_ref_os:', e.message); }
try {
const res = await request(apiBase + '/collections/z_ref_os_version/records?perPage=500&expand=os', { headers: { 'Authorization': token } });
if (res.ok) {
(JSON.parse(res.body).items || []).forEach(function(item) {
var osName = item.expand && item.expand.os && item.expand.os.os != null ? item.expand.os.os : null;
if (osName != null && item.version != null) osVersionToId[osName + '|' + item.version] = item.id;
});
}
} catch (e) { console.warn('z_ref_os_version:', e.message); }
var notesCollUrl = apiBase + '/collections/script_notes/records';
var installMethodsCollUrl = apiBase + '/collections/script_install_methods/records';
for (const file of files) {
if (!fs.existsSync(file)) continue;
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
if (!data.slug) { console.log('Skipping', file, '(no slug)'); continue; }
var payload = {
name: data.name,
slug: data.slug,
script_created: data.date_created || data.script_created,
script_updated: data.date_created || data.script_updated,
updateable: data.updateable,
privileged: data.privileged,
port: data.interface_port != null ? data.interface_port : data.port,
documentation: data.documentation,
website: data.website,
logo: data.logo,
description: data.description,
config_path: data.config_path,
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd,
is_dev: false
};
var resolvedType = typeValueToId[data.type];
if (resolvedType == null && data.type === 'ct') resolvedType = typeValueToId['lxc'];
if (resolvedType) payload.type = resolvedType;
var resolvedCats = (data.categories || []).map(function(n) { return categoryNameToPbId[categoryIdToName[n]]; }).filter(Boolean);
if (resolvedCats.length) payload.categories = resolvedCats;
if (data.version !== undefined) payload.version = data.version;
if (data.changelog !== undefined) payload.changelog = data.changelog;
if (data.screenshots !== undefined) payload.screenshots = data.screenshots;
const filter = "(slug='" + data.slug + "')";
const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
headers: { 'Authorization': token }
});
const list = JSON.parse(listRes.body);
const existingId = list.items && list.items[0] && list.items[0].id;
async function resolveNotesAndInstallMethods(scriptId) {
var noteIds = [];
for (var i = 0; i < (data.notes || []).length; i++) {
var note = data.notes[i];
var typeId = noteTypeToId[note.type];
if (typeId == null) continue;
var postRes = await request(notesCollUrl, {
method: 'POST',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ text: note.text || '', type: typeId })
});
if (postRes.ok) noteIds.push(JSON.parse(postRes.body).id);
}
var installMethodIds = [];
for (var j = 0; j < (data.install_methods || []).length; j++) {
var im = data.install_methods[j];
var typeId = installMethodTypeToId[im.type];
var res = im.resources || {};
var osId = osToId[res.os];
var osVersionKey = (res.os != null && res.version != null) ? res.os + '|' + res.version : null;
var osVersionId = osVersionKey ? osVersionToId[osVersionKey] : null;
var imBody = {
script: scriptId,
resources_cpu: res.cpu != null ? res.cpu : 0,
resources_ram: res.ram != null ? res.ram : 0,
resources_hdd: res.hdd != null ? res.hdd : 0
};
if (typeId) imBody.type = typeId;
if (osId) imBody.os = osId;
if (osVersionId) imBody.os_version = osVersionId;
var imPostRes = await request(installMethodsCollUrl, {
method: 'POST',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(imBody)
});
if (imPostRes.ok) installMethodIds.push(JSON.parse(imPostRes.body).id);
}
return { noteIds: noteIds, installMethodIds: installMethodIds };
}
if (existingId) {
var resolved = await resolveNotesAndInstallMethods(existingId);
payload.notes = resolved.noteIds;
payload.install_methods = resolved.installMethodIds;
console.log('Updating', file, '(slug=' + data.slug + ')');
const r = await request(recordsUrl + '/' + existingId, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r.ok) throw new Error('PATCH failed: ' + r.body);
} else {
console.log('Creating', file, '(slug=' + data.slug + ')');
const r = await request(recordsUrl, {
method: 'POST',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r.ok) throw new Error('POST failed: ' + r.body);
var scriptId = JSON.parse(r.body).id;
var resolved = await resolveNotesAndInstallMethods(scriptId);
var patchRes = await request(recordsUrl + '/' + scriptId, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ install_methods: resolved.installMethodIds, notes: resolved.noteIds })
});
if (!patchRes.ok) throw new Error('PATCH relations failed: ' + patchRes.body);
}
}
console.log('Done.');
})().catch(e => { console.error(e); process.exit(1); });
ENDSCRIPT
shell: bash

View File

@@ -21,9 +21,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details> <details>
<summary><h2>📜 History</h2></summary> <summary><h2>📜 History</h2></summary>
@@ -33,7 +30,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details> <details>
<summary><h4>February (28 entries)</h4></summary> <summary><h4>February (21 entries)</h4></summary>
[View February 2026 Changelog](.github/changelogs/2026/02.md) [View February 2026 Changelog](.github/changelogs/2026/02.md)
@@ -410,227 +407,27 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details> </details>
## 2026-03-03
### 🆕 New Scripts
- Tinyauth: v5 Support & add Debian Version [@MickLesk](https://github.com/MickLesk) ([#12501](https://github.com/community-scripts/ProxmoxVE/pull/12501))
### 🗑️ Deleted Scripts
- Remove Unifi Network Server scripts (dead APT repo) [@Copilot](https://github.com/Copilot) ([#12500](https://github.com/community-scripts/ProxmoxVE/pull/12500))
### 🌐 Website
- #### 🐞 Bug Fixes
- Revert #11534 PR that messed up search [@BramSuurdje](https://github.com/BramSuurdje) ([#12492](https://github.com/community-scripts/ProxmoxVE/pull/12492))
## 2026-03-02
### 🆕 New Scripts
- PowerDNS ([#12481](https://github.com/community-scripts/ProxmoxVE/pull/12481))
- Profilarr ([#12441](https://github.com/community-scripts/ProxmoxVE/pull/12441))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Tracearr: prepare for imminent v1.4.19 release [@durzo](https://github.com/durzo) ([#12413](https://github.com/community-scripts/ProxmoxVE/pull/12413))
- #### ✨ New Features
- Frigate: Bump to v0.17 [@MickLesk](https://github.com/MickLesk) ([#12474](https://github.com/community-scripts/ProxmoxVE/pull/12474))
- #### 💥 Breaking Changes
- Migrate: DokPloy, Komodo, Coolify, Dockge, Runtipi to Addons [@MickLesk](https://github.com/MickLesk) ([#12275](https://github.com/community-scripts/ProxmoxVE/pull/12275))
- #### 🔧 Refactor
- ref: replace generic exit 1 with specific exit codes in ct & install [@MickLesk](https://github.com/MickLesk) ([#12475](https://github.com/community-scripts/ProxmoxVE/pull/12475))
### 💾 Core
- #### ✨ New Features
- tools.func: Improve stability with retry logic, caching, and debug mode [@MickLesk](https://github.com/MickLesk) ([#10351](https://github.com/community-scripts/ProxmoxVE/pull/10351))
- #### 🔧 Refactor
- core: standardize exit codes and add mappings [@MickLesk](https://github.com/MickLesk) ([#12467](https://github.com/community-scripts/ProxmoxVE/pull/12467))
### 🌐 Website
- frontend: improve detail view badges, addon texts, and HTML title [@MickLesk](https://github.com/MickLesk) ([#12461](https://github.com/community-scripts/ProxmoxVE/pull/12461))
## 2026-03-01
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Sparkyfitness: use pnpm [@tomfrenzel](https://github.com/tomfrenzel) ([#12445](https://github.com/community-scripts/ProxmoxVE/pull/12445))
- OpenArchiver: Fix installation [@tremor021](https://github.com/tremor021) ([#12447](https://github.com/community-scripts/ProxmoxVE/pull/12447))
## 2026-02-28
### 🚀 Updated Scripts
- Update Reactive Resume install script with useful .env information for reverse proxy setup [@Mazianni](https://github.com/Mazianni) ([#12401](https://github.com/community-scripts/ProxmoxVE/pull/12401))
- #### 🐞 Bug Fixes
- gramps-web: install addons (FilterRules) for relationship diagram [@MickLesk](https://github.com/MickLesk) ([#12387](https://github.com/community-scripts/ProxmoxVE/pull/12387))
- [Fix] Immich: Change `sed` command to fully replace line in postgresql.conf [@vhsdream](https://github.com/vhsdream) ([#12429](https://github.com/community-scripts/ProxmoxVE/pull/12429))
- [FIX] Immich: fix Openvino memory leak during OCR; improve HW-accelerated ML performance [@vhsdream](https://github.com/vhsdream) ([#12426](https://github.com/community-scripts/ProxmoxVE/pull/12426))
- Fix default tag for ioBroker LXC install [@josefglatz](https://github.com/josefglatz) ([#12423](https://github.com/community-scripts/ProxmoxVE/pull/12423))
- Ombi: Add database.json [@hraphael](https://github.com/hraphael) ([#12412](https://github.com/community-scripts/ProxmoxVE/pull/12412))
- Dawarich: add missing build deps and handle seed failure [@MickLesk](https://github.com/MickLesk) ([#12410](https://github.com/community-scripts/ProxmoxVE/pull/12410))
- pangolin: increase hdd to 10G [@MickLesk](https://github.com/MickLesk) ([#12409](https://github.com/community-scripts/ProxmoxVE/pull/12409))
- #### ✨ New Features
- BookLore: add additional JVM flags [@vhsdream](https://github.com/vhsdream) ([#12421](https://github.com/community-scripts/ProxmoxVE/pull/12421))
### 🗑️ Deleted Scripts
- Delete Palmr [@vhsdream](https://github.com/vhsdream) ([#12399](https://github.com/community-scripts/ProxmoxVE/pull/12399))
### 💾 Core
- #### 🐞 Bug Fixes
- core: read from /dev/tty in all interactive prompts | fix empty or cropped logs due build process [@MickLesk](https://github.com/MickLesk) ([#12406](https://github.com/community-scripts/ProxmoxVE/pull/12406))
## 2026-02-27
### 🆕 New Scripts
- Strapi ([#12320](https://github.com/community-scripts/ProxmoxVE/pull/12320))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- TrueNAS VM: filter out new nightlies with MASTER [@juronja](https://github.com/juronja) ([#12355](https://github.com/community-scripts/ProxmoxVE/pull/12355))
### 💾 Core
- #### ✨ New Features
- core: graceful fallback for apt-get update failures [@MickLesk](https://github.com/MickLesk) ([#12386](https://github.com/community-scripts/ProxmoxVE/pull/12386))
- core: Improve error outputs across core functions [@MickLesk](https://github.com/MickLesk) ([#12378](https://github.com/community-scripts/ProxmoxVE/pull/12378))
## 2026-02-26
### 🆕 New Scripts
- Kima-Hub ([#12319](https://github.com/community-scripts/ProxmoxVE/pull/12319))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- tools.func: update glx alternatives / nvidia alternative if nvidia glx are missing [@MickLesk](https://github.com/MickLesk) ([#12372](https://github.com/community-scripts/ProxmoxVE/pull/12372))
- hotfix: overseer version [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12366](https://github.com/community-scripts/ProxmoxVE/pull/12366))
- #### ✨ New Features
- Add ffmpeg for booklore (ffprobe) [@MickLesk](https://github.com/MickLesk) ([#12371](https://github.com/community-scripts/ProxmoxVE/pull/12371))
- [QOL] Immich: add warning regarding library compilation time [@vhsdream](https://github.com/vhsdream) ([#12345](https://github.com/community-scripts/ProxmoxVE/pull/12345))
### 🧰 Tools
- #### 🐞 Bug Fixes
- Improves adguardhome-sync addon when running on alpine LXCs [@Darkangeel-hd](https://github.com/Darkangeel-hd) ([#12362](https://github.com/community-scripts/ProxmoxVE/pull/12362))
- #### ✨ New Features
- Add Alpine support and improve Tailscale install [@MickLesk](https://github.com/MickLesk) ([#12370](https://github.com/community-scripts/ProxmoxVE/pull/12370))
### 📚 Documentation
- fix wrong link on contributions README.md [@Darkangeel-hd](https://github.com/Darkangeel-hd) ([#12363](https://github.com/community-scripts/ProxmoxVE/pull/12363))
### 📂 Github
- github: add workflow to autom. close unauthorized new-script PRs [@MickLesk](https://github.com/MickLesk) ([#12356](https://github.com/community-scripts/ProxmoxVE/pull/12356))
## 2026-02-25
### 🆕 New Scripts
- Zerobyte ([#12321](https://github.com/community-scripts/ProxmoxVE/pull/12321))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: overseer migration [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12340](https://github.com/community-scripts/ProxmoxVE/pull/12340))
- add: vikunja: daemon reload [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12323](https://github.com/community-scripts/ProxmoxVE/pull/12323))
- opnsense-VM: Use ip link to verify bridge existence [@MickLesk](https://github.com/MickLesk) ([#12329](https://github.com/community-scripts/ProxmoxVE/pull/12329))
- wger: Use $http_host for proxy Host header [@MickLesk](https://github.com/MickLesk) ([#12327](https://github.com/community-scripts/ProxmoxVE/pull/12327))
- Passbolt: Update Nginx config `client_max_body_size` [@tremor021](https://github.com/tremor021) ([#12313](https://github.com/community-scripts/ProxmoxVE/pull/12313))
- Zammad: configure Elasticsearch before zammad start [@MickLesk](https://github.com/MickLesk) ([#12308](https://github.com/community-scripts/ProxmoxVE/pull/12308))
- #### 🔧 Refactor
- OpenProject: Various fixes [@tremor021](https://github.com/tremor021) ([#12246](https://github.com/community-scripts/ProxmoxVE/pull/12246))
### 💾 Core
- #### 🐞 Bug Fixes
- Fix detection of ssh keys [@1-tempest](https://github.com/1-tempest) ([#12230](https://github.com/community-scripts/ProxmoxVE/pull/12230))
- #### ✨ New Features
- tools.func: Improve GitHub/Codeberg API error handling and error output [@MickLesk](https://github.com/MickLesk) ([#12330](https://github.com/community-scripts/ProxmoxVE/pull/12330))
- #### 🔧 Refactor
- core: remove duplicate traps, consolidate error handling and harden signal traps [@MickLesk](https://github.com/MickLesk) ([#12316](https://github.com/community-scripts/ProxmoxVE/pull/12316))
### 📂 Github
- github: improvements for node drift wf [@MickLesk](https://github.com/MickLesk) ([#12309](https://github.com/community-scripts/ProxmoxVE/pull/12309))
## 2026-02-24 ## 2026-02-24
### 🚀 Updated Scripts ### 🚀 Updated Scripts
- several scripts: add additional github link in source [@MickLesk](https://github.com/MickLesk) ([#12282](https://github.com/community-scripts/ProxmoxVE/pull/12282)) - adds further documentation during the installation script. [@d12rio](https://github.com/d12rio) ([#12248](https://github.com/community-scripts/ProxmoxVE/pull/12248))
- adds further documentation during the installation script. [@d12rio](https://github.com/d12rio) ([#12248](https://github.com/community-scripts/ProxmoxVE/pull/12248))
- #### 🐞 Bug Fixes - #### 🐞 Bug Fixes
- [Fix] PatchMon: remove VITE_API_URL from frontend env [@vhsdream](https://github.com/vhsdream) ([#12294](https://github.com/community-scripts/ProxmoxVE/pull/12294))
- fix(searxng): remove orphaned fi causing syntax error [@mark-jeffrey](https://github.com/mark-jeffrey) ([#12283](https://github.com/community-scripts/ProxmoxVE/pull/12283))
- Refactor n8n [@MickLesk](https://github.com/MickLesk) ([#12264](https://github.com/community-scripts/ProxmoxVE/pull/12264)) - Refactor n8n [@MickLesk](https://github.com/MickLesk) ([#12264](https://github.com/community-scripts/ProxmoxVE/pull/12264))
- Firefly: PHP bump [@tremor021](https://github.com/tremor021) ([#12247](https://github.com/community-scripts/ProxmoxVE/pull/12247)) - Firefly: PHP bump [@tremor021](https://github.com/tremor021) ([#12247](https://github.com/community-scripts/ProxmoxVE/pull/12247))
- #### ✨ New Features - #### ✨ New Features
- Databasus: add mariadb path for mysql/mariadb backups | add mongodb database tools [@MickLesk](https://github.com/MickLesk) ([#12259](https://github.com/community-scripts/ProxmoxVE/pull/12259))
- make searxng updateable [@shtefko](https://github.com/shtefko) ([#12207](https://github.com/community-scripts/ProxmoxVE/pull/12207)) - make searxng updateable [@shtefko](https://github.com/shtefko) ([#12207](https://github.com/community-scripts/ProxmoxVE/pull/12207))
- #### 💥 Breaking Changes
- fix: wealthfolio for v3 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11765](https://github.com/community-scripts/ProxmoxVE/pull/11765))
- #### 🔧 Refactor - #### 🔧 Refactor
- bump various scripts from Node 22 to 24 [@MickLesk](https://github.com/MickLesk) ([#12265](https://github.com/community-scripts/ProxmoxVE/pull/12265)) - bump various scripts from Node 22 to 24 [@MickLesk](https://github.com/MickLesk) ([#12265](https://github.com/community-scripts/ProxmoxVE/pull/12265))
### 💾 Core ### 💾 Core
- #### 🐞 Bug Fixes
- core: fix broken "command not found" after err_trap [@MickLesk](https://github.com/MickLesk) ([#12280](https://github.com/community-scripts/ProxmoxVE/pull/12280))
- #### ✨ New Features - #### ✨ New Features
- tools.func: add get_latest_gh_tag helper function [@MickLesk](https://github.com/MickLesk) ([#12261](https://github.com/community-scripts/ProxmoxVE/pull/12261)) - tools.func: add get_latest_gh_tag helper function [@MickLesk](https://github.com/MickLesk) ([#12261](https://github.com/community-scripts/ProxmoxVE/pull/12261))
@@ -1411,4 +1208,241 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### ✨ New Features - #### ✨ New Features
- [tools] Add `fetch_and_deploy_from_url()` [@tremor021](https://github.com/tremor021) ([#11376](https://github.com/community-scripts/ProxmoxVE/pull/11376)) - [tools] Add `fetch_and_deploy_from_url()` [@tremor021](https://github.com/tremor021) ([#11376](https://github.com/community-scripts/ProxmoxVE/pull/11376))
- core: php - improve module handling and prevent installation failures [@MickLesk](https://github.com/MickLesk) ([#11358](https://github.com/community-scripts/ProxmoxVE/pull/11358)) - core: php - improve module handling and prevent installation failures [@MickLesk](https://github.com/MickLesk) ([#11358](https://github.com/community-scripts/ProxmoxVE/pull/11358))
## 2026-01-29
### 🆕 New Scripts
- Alpine-Valkey [@MickLesk](https://github.com/MickLesk) ([#11320](https://github.com/community-scripts/ProxmoxVE/pull/11320))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Immich: Pin version to 2.5.2 [@vhsdream](https://github.com/vhsdream) ([#11335](https://github.com/community-scripts/ProxmoxVE/pull/11335))
- Kollection: Update to php 8.5 [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#11315](https://github.com/community-scripts/ProxmoxVE/pull/11315))
- Notifiarr: change installation check from apt to systemd service [@MickLesk](https://github.com/MickLesk) ([#11319](https://github.com/community-scripts/ProxmoxVE/pull/11319))
- #### ✨ New Features
- [FEAT] Immich: Enable Maintenance Mode before update [@vhsdream](https://github.com/vhsdream) ([#11342](https://github.com/community-scripts/ProxmoxVE/pull/11342))
- jellyfin: add logrotate instead of reducing log level [@MickLesk](https://github.com/MickLesk) ([#11326](https://github.com/community-scripts/ProxmoxVE/pull/11326))
- core: Add config file handling options | Fix Vikunja update with interactive overwrite [@MickLesk](https://github.com/MickLesk) ([#11317](https://github.com/community-scripts/ProxmoxVE/pull/11317))
- Immich: v2.5.0 [@vhsdream](https://github.com/vhsdream) ([#11240](https://github.com/community-scripts/ProxmoxVE/pull/11240))
- #### 💥 Breaking Changes
- fix: vikunja v1 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11308](https://github.com/community-scripts/ProxmoxVE/pull/11308))
- #### 🔧 Refactor
- Refactor: Byparr [@vhsdream](https://github.com/vhsdream) ([#11338](https://github.com/community-scripts/ProxmoxVE/pull/11338))
- cloudflare: Remove deprecated DNS-over-HTTPS proxy option [@MickLesk](https://github.com/MickLesk) ([#11068](https://github.com/community-scripts/ProxmoxVE/pull/11068))
### 💾 Core
- #### 🐞 Bug Fixes
- build.func: Replace storage variable with searchdomain variable [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#11322](https://github.com/community-scripts/ProxmoxVE/pull/11322))
### 📂 Github
- Add workflow to lock closed issues [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#11316](https://github.com/community-scripts/ProxmoxVE/pull/11316))
## 2026-01-28
### 🆕 New Scripts
- nodecast-tv ([#11287](https://github.com/community-scripts/ProxmoxVE/pull/11287))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Ubuntu 25.04 VM - Change default start from yes to no [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#11292](https://github.com/community-scripts/ProxmoxVE/pull/11292))
- #### ✨ New Features
- various scripts: use setup_meilisearch function [@MickLesk](https://github.com/MickLesk) ([#11259](https://github.com/community-scripts/ProxmoxVE/pull/11259))
- #### 🔧 Refactor
- Refactor: NPMPlus / Default Login [@MickLesk](https://github.com/MickLesk) ([#11262](https://github.com/community-scripts/ProxmoxVE/pull/11262))
### 💾 Core
- #### 🐞 Bug Fixes
- core: sed patch for ram [@lavacano](https://github.com/lavacano) ([#11285](https://github.com/community-scripts/ProxmoxVE/pull/11285))
- Fix installer loop caused by invalid whiptail menu separator [@Mesteriis](https://github.com/Mesteriis) ([#11237](https://github.com/community-scripts/ProxmoxVE/pull/11237))
- core: fix Debian 13 LXC template root ownership bug [@MickLesk](https://github.com/MickLesk) ([#11277](https://github.com/community-scripts/ProxmoxVE/pull/11277))
- tools.func: prevent systemd-tmpfiles failure in unprivileged LXC during deb install [@MickLesk](https://github.com/MickLesk) ([#11271](https://github.com/community-scripts/ProxmoxVE/pull/11271))
- tools.func: fix php "wait_for" hint [@MickLesk](https://github.com/MickLesk) ([#11254](https://github.com/community-scripts/ProxmoxVE/pull/11254))
- #### ✨ New Features
- core: update dynamic values in LXC profile on update_motd_ip [@MickLesk](https://github.com/MickLesk) ([#11268](https://github.com/community-scripts/ProxmoxVE/pull/11268))
- tools.func: add new function - setup_meilisearch [@MickLesk](https://github.com/MickLesk) ([#11258](https://github.com/community-scripts/ProxmoxVE/pull/11258))
### 📂 Github
- github: add GitHub-based versions.json updater [@MickLesk](https://github.com/MickLesk) ([#10021](https://github.com/community-scripts/ProxmoxVE/pull/10021))
### 🌐 Website
- #### ✨ New Features
- Frontend: use github-versions.json for version display [@MickLesk](https://github.com/MickLesk) ([#11281](https://github.com/community-scripts/ProxmoxVE/pull/11281))
- #### 📝 Script Information
- fix: homarr: conf location [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11253](https://github.com/community-scripts/ProxmoxVE/pull/11253))
## 2026-01-27
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Immich: update libraw [@vhsdream](https://github.com/vhsdream) ([#11233](https://github.com/community-scripts/ProxmoxVE/pull/11233))
- #### ✨ New Features
- grist: enable optional enterprise features toggle [@MickLesk](https://github.com/MickLesk) ([#11239](https://github.com/community-scripts/ProxmoxVE/pull/11239))
- #### 🔧 Refactor
- Termix: use nginx.conf from upstream repo [@MickLesk](https://github.com/MickLesk) ([#11228](https://github.com/community-scripts/ProxmoxVE/pull/11228))
### 💾 Core
- #### ✨ New Features
- feat: add NVIDIA driver install prompt for GPU-enabled containers [@devdecrux](https://github.com/devdecrux) ([#11184](https://github.com/community-scripts/ProxmoxVE/pull/11184))
### 📚 Documentation
- doc setup_deb822_repo arg order [@chrnie](https://github.com/chrnie) ([#11215](https://github.com/community-scripts/ProxmoxVE/pull/11215))
- changelog: archive old entries to year/month files [@MickLesk](https://github.com/MickLesk) ([#11225](https://github.com/community-scripts/ProxmoxVE/pull/11225))
## 2026-01-26
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Ghost: Fix missing dependency [@tremor021](https://github.com/tremor021) ([#11196](https://github.com/community-scripts/ProxmoxVE/pull/11196))
- tracearr: fix install check and update node to version 24 [@durzo](https://github.com/durzo) ([#11188](https://github.com/community-scripts/ProxmoxVE/pull/11188))
- #### ✨ New Features
- jotty: full refactor / prebuild package [@MickLesk](https://github.com/MickLesk) ([#11059](https://github.com/community-scripts/ProxmoxVE/pull/11059))
- #### 💥 Breaking Changes
- Termix: Fixing Nginx configuration for 1.11.0 installs (read description for fix!) [@8b1th3r0](https://github.com/8b1th3r0) ([#11207](https://github.com/community-scripts/ProxmoxVE/pull/11207))
### 💾 Core
- #### 🐞 Bug Fixes
- core: refine cleanup_lxc to safely clear caches [@MickLesk](https://github.com/MickLesk) ([#11197](https://github.com/community-scripts/ProxmoxVE/pull/11197))
- #### ✨ New Features
- core: add nesting warning for systemd-based distributions [@MickLesk](https://github.com/MickLesk) ([#11208](https://github.com/community-scripts/ProxmoxVE/pull/11208))
### 🧰 Tools
- #### 🐞 Bug Fixes
- jellystat: correct WorkingDirectory to /backend [@MickLesk](https://github.com/MickLesk) ([#11201](https://github.com/community-scripts/ProxmoxVE/pull/11201))
## 2026-01-25
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- [FIX] Tautulli: ensure virtualenv is recreated during update; backup tautulli.db [@vhsdream](https://github.com/vhsdream) ([#11182](https://github.com/community-scripts/ProxmoxVE/pull/11182))
- [Fix] Pangolin: ensure additional JSON files are in place [@vhsdream](https://github.com/vhsdream) ([#11183](https://github.com/community-scripts/ProxmoxVE/pull/11183))
- Manyfold: fix permissions error [@vhsdream](https://github.com/vhsdream) ([#11165](https://github.com/community-scripts/ProxmoxVE/pull/11165))
- Termix: recreate nginx dirs and backup uploads on update [@MickLesk](https://github.com/MickLesk) ([#11169](https://github.com/community-scripts/ProxmoxVE/pull/11169))
- Deluge: correct service paths to /usr/local/bin [@MickLesk](https://github.com/MickLesk) ([#11170](https://github.com/community-scripts/ProxmoxVE/pull/11170))
- #### ✨ New Features
- Karakeep: Add the FFmpeg option to the installation script [@vonhyou](https://github.com/vonhyou) ([#11157](https://github.com/community-scripts/ProxmoxVE/pull/11157))
- apt-cacher-ng: add avahi-daemon for mDNS service discovery [@MickLesk](https://github.com/MickLesk) ([#11140](https://github.com/community-scripts/ProxmoxVE/pull/11140))
## 2026-01-24
### 🆕 New Scripts
- Manyfold ([#11143](https://github.com/community-scripts/ProxmoxVE/pull/11143))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- elementsynapse: correct parameter order in fetch_and_deploy_gh_release [@MickLesk](https://github.com/MickLesk) ([#11145](https://github.com/community-scripts/ProxmoxVE/pull/11145))
- leantime: fix backup file naming [@MickLesk](https://github.com/MickLesk) ([#11137](https://github.com/community-scripts/ProxmoxVE/pull/11137))
- [Hotfix] Element Synapse [@vhsdream](https://github.com/vhsdream) ([#11135](https://github.com/community-scripts/ProxmoxVE/pull/11135))
- authelia: use POSIX-safe arithmetic to avoid exit code 1 with set -e in subshells [@MickLesk](https://github.com/MickLesk) ([#11125](https://github.com/community-scripts/ProxmoxVE/pull/11125))
- Bitmagnet: PostgreSQL and environment variable fixes [@tremor021](https://github.com/tremor021) ([#11119](https://github.com/community-scripts/ProxmoxVE/pull/11119))
- Spoolman: move to uv [@vhsdream](https://github.com/vhsdream) ([#11121](https://github.com/community-scripts/ProxmoxVE/pull/11121))
- #### 🔧 Refactor
- bump crafty-controller to debian 13 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11094](https://github.com/community-scripts/ProxmoxVE/pull/11094))
- Netbox: Refactor [@vhsdream](https://github.com/vhsdream) ([#11126](https://github.com/community-scripts/ProxmoxVE/pull/11126))
- Flatnotes: Standard enforcing [@tremor021](https://github.com/tremor021) ([#11109](https://github.com/community-scripts/ProxmoxVE/pull/11109))
### 💾 Core
- #### 🐞 Bug Fixes
- nvidia: use versioned nvidia-utils package for Ubuntu fallback [@MickLesk](https://github.com/MickLesk) ([#11139](https://github.com/community-scripts/ProxmoxVE/pull/11139))
### 🌐 Website
- #### 📝 Script Information
- Byparr: Add config file path to website [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11120](https://github.com/community-scripts/ProxmoxVE/pull/11120))
## 2026-01-23
### 🆕 New Scripts
- Tracearr ([#11079](https://github.com/community-scripts/ProxmoxVE/pull/11079))
- Dawarich ([#11075](https://github.com/community-scripts/ProxmoxVE/pull/11075))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: homarr: more ram [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11102](https://github.com/community-scripts/ProxmoxVE/pull/11102))
- plant-it: re-add JWT_SECRET [@MickLesk](https://github.com/MickLesk) ([#11098](https://github.com/community-scripts/ProxmoxVE/pull/11098))
- Tautulli: fix config backup and restore logic [@MickLesk](https://github.com/MickLesk) ([#11099](https://github.com/community-scripts/ProxmoxVE/pull/11099))
- Scanopy: remove integrated daemon script [@vhsdream](https://github.com/vhsdream) ([#11100](https://github.com/community-scripts/ProxmoxVE/pull/11100))
- fix: reitti start nginx [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11095](https://github.com/community-scripts/ProxmoxVE/pull/11095))
- add: uptime-kuma: chromium [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11081](https://github.com/community-scripts/ProxmoxVE/pull/11081))
- fix(install): Add typing_extensions to SearXNG Python dependencies [@ZarenOFF](https://github.com/ZarenOFF) ([#11074](https://github.com/community-scripts/ProxmoxVE/pull/11074))
- #### ✨ New Features
- Bump various scripts to Debian 13 (Trixie) [@MickLesk](https://github.com/MickLesk) ([#11093](https://github.com/community-scripts/ProxmoxVE/pull/11093))
- several scripts: bump default Alpine version to 3.23 [@MickLesk](https://github.com/MickLesk) ([#11082](https://github.com/community-scripts/ProxmoxVE/pull/11082))
- PDM: avoid installing useless package [@LongQT-sea](https://github.com/LongQT-sea) ([#10833](https://github.com/community-scripts/ProxmoxVE/pull/10833))
- #### 🔧 Refactor
- FHEM: Bump to Debian 13 [@tremor021](https://github.com/tremor021) ([#11061](https://github.com/community-scripts/ProxmoxVE/pull/11061))
- Duplicati: Bump to Debian 13 [@tremor021](https://github.com/tremor021) ([#11060](https://github.com/community-scripts/ProxmoxVE/pull/11060))
### 💾 Core
- #### ✨ New Features
- core: add IPv6 fallback support to get_current_ip functions | add check for SSH_KEYS_FILE in user_defaults [@MickLesk](https://github.com/MickLesk) ([#11067](https://github.com/community-scripts/ProxmoxVE/pull/11067))

View File

@@ -19,46 +19,44 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh"
function update_script() { function update_script() {
if [[ ! -d /opt/komodo ]]; then [[ -d /opt/komodo ]] || {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi }
msg_warn "⚠️ ${APP} has been migrated to an addon script." msg_info "Updating ${APP}"
echo "" COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:" if [[ -z "$COMPOSE_FILE" ]]; then
echo -e "${TAB}${TAB}${GN}update_komodo${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}" msg_error "No valid compose file found in /opt/komodo!"
echo "" exit
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM fi
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)" if [[ "$COMPOSE_BASENAME" == "sqlite.compose.yaml" || "$COMPOSE_BASENAME" == "postgres.compose.yaml" ]]; then
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1) msg_error "❌ Detected outdated Komodo setup using SQLite or PostgreSQL (FerretDB v1)."
if [[ -z "$COMPOSE_FILE" ]]; then echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}"
msg_error "No valid compose file found in /opt/komodo!" echo -e "${YW}Please follow the migration guide:${CL}"
exit 252 echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n"
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated ${APP}"
exit exit
fi fi
msg_info "Migrating update function" BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
cat <<'MIGRATION_EOF' >/usr/bin/update cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)" msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
MIGRATION_EOF exit
chmod +x /usr/bin/update }
GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
ln -sf /usr/bin/update /usr/bin/update_komodo 2>/dev/null || true if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_ok "Migration complete" msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
mv "$BACKUP_FILE" "$COMPOSE_FILE"
msg_info "Running addon update" exit
type=update bash <(curl -fsSL "${ADDON_SCRIPT}") fi
exit $STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated Alpine-Komodo"
msg_ok "Updated successfully!"
exit 0
} }
start start

View File

@@ -35,20 +35,6 @@ function update_script() {
$STD service tinyauth stop $STD service tinyauth stop
msg_ok "Service Stopped" msg_ok "Service Stopped"
if [[ -f /opt/tinyauth/.env ]] && ! grep -q "^TINYAUTH_" /opt/tinyauth/.env; then
msg_info "Migrating .env to v5 format"
sed -i \
-e 's/^DATABASE_PATH=/TINYAUTH_DATABASE_PATH=/' \
-e 's/^USERS=/TINYAUTH_AUTH_USERS=/' \
-e "s/^USERS='/TINYAUTH_AUTH_USERS='/" \
-e 's/^APP_URL=/TINYAUTH_APPURL=/' \
-e 's/^SECRET=/TINYAUTH_AUTH_SECRET=/' \
-e 's/^PORT=/TINYAUTH_SERVER_PORT=/' \
-e 's/^ADDRESS=/TINYAUTH_SERVER_ADDRESS=/' \
/opt/tinyauth/.env
msg_ok "Migrated .env to v5 format"
fi
msg_info "Updating Tinyauth" msg_info "Updating Tinyauth"
rm -f /opt/tinyauth/tinyauth rm -f /opt/tinyauth/tinyauth
curl -fsSL "https://github.com/steveiliop56/tinyauth/releases/download/v${RELEASE}/tinyauth-amd64" -o /opt/tinyauth/tinyauth curl -fsSL "https://github.com/steveiliop56/tinyauth/releases/download/v${RELEASE}/tinyauth-amd64" -o /opt/tinyauth/tinyauth

View File

@@ -34,7 +34,6 @@ function update_script() {
NODE_VERSION="22" setup_nodejs NODE_VERSION="22" setup_nodejs
setup_mariadb setup_mariadb
setup_yq setup_yq
ensure_dependencies ffmpeg
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop booklore systemctl stop booklore
@@ -91,7 +90,7 @@ function update_script() {
echo "SERVER_PORT=6060" >>/opt/booklore_storage/.env echo "SERVER_PORT=6060" >>/opt/booklore_storage/.env
fi fi
sed -i 's|ExecStart=.*|ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError -jar /opt/booklore/dist/app.jar|' /etc/systemd/system/booklore.service sed -i 's|ExecStart=/usr/bin/java -jar|ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -jar|' /etc/systemd/system/booklore.service
systemctl daemon-reload systemctl daemon-reload
msg_info "Starting Service" msg_info "Starting Service"

View File

@@ -19,8 +19,6 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh"
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
@@ -31,31 +29,10 @@ function update_script() {
exit exit
fi fi
msg_warn "⚠️ ${APP} has been migrated to an addon script." msg_info "Updating Coolify"
echo "" $STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:" msg_ok "Updated Coolify"
echo -e "${TAB}${TAB}${GN}update_coolify${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}" msg_ok "Updated successfully!"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_coolify 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit exit
} }

View File

@@ -38,31 +38,6 @@ function update_script() {
cp /opt/databasus/.env /opt/databasus.env.bak cp /opt/databasus/.env /opt/databasus.env.bak
msg_ok "Backed up Configuration" msg_ok "Backed up Configuration"
msg_info "Ensuring Database Clients"
# Create PostgreSQL version symlinks for compatibility
for v in 12 13 14 15 16 18; do
ln -sf /usr/lib/postgresql/17 /usr/lib/postgresql/$v
done
# Install MongoDB Database Tools via direct .deb (no APT repo for Debian 13)
if ! command -v mongodump &>/dev/null; then
[[ "$(get_os_info id)" == "ubuntu" ]] && MONGO_DIST="ubuntu2204" || MONGO_DIST="debian12"
fetch_and_deploy_from_url "https://fastdl.mongodb.org/tools/db/mongodb-database-tools-${MONGO_DIST}-x86_64-100.14.1.deb"
fi
[[ -f /usr/bin/mongodump ]] && ln -sf /usr/bin/mongodump /usr/local/mongodb-database-tools/bin/mongodump
[[ -f /usr/bin/mongorestore ]] && ln -sf /usr/bin/mongorestore /usr/local/mongodb-database-tools/bin/mongorestore
# Create MariaDB and MySQL client symlinks for compatibility
ensure_dependencies mariadb-client
mkdir -p /usr/local/mariadb-{10.6,12.1}/bin /usr/local/mysql-{5.7,8.0,8.4,9}/bin /usr/local/mongodb-database-tools/bin
for dir in /usr/local/mariadb-{10.6,12.1}/bin; do
ln -sf /usr/bin/mariadb-dump "$dir/mariadb-dump"
ln -sf /usr/bin/mariadb "$dir/mariadb"
done
for dir in /usr/local/mysql-{5.7,8.0,8.4,9}/bin; do
ln -sf /usr/bin/mariadb-dump "$dir/mysqldump"
ln -sf /usr/bin/mariadb "$dir/mysql"
done
msg_ok "Ensured Database Clients"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "databasus" "databasus/databasus" "tarball" "latest" "/opt/databasus" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "databasus" "databasus/databasus" "tarball" "latest" "/opt/databasus"
msg_info "Updating Databasus" msg_info "Updating Databasus"
@@ -74,7 +49,6 @@ function update_script() {
$STD /root/go/bin/swag init -g cmd/main.go -o swagger $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 $STD env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o databasus ./cmd/main.go
mv /opt/databasus/backend/databasus /opt/databasus/databasus mv /opt/databasus/backend/databasus /opt/databasus/databasus
mkdir -p /opt/databasus/ui/build
cp -r /opt/databasus/frontend/dist/* /opt/databasus/ui/build/ cp -r /opt/databasus/frontend/dist/* /opt/databasus/ui/build/
cp -r /opt/databasus/backend/migrations /opt/databasus/ cp -r /opt/databasus/backend/migrations /opt/databasus/
chown -R postgres:postgres /opt/databasus chown -R postgres:postgres /opt/databasus

View File

@@ -29,8 +29,6 @@ function update_script() {
exit exit
fi fi
ensure_dependencies libgeos++-dev libxml2-dev libxslt-dev libjemalloc-dev
if check_for_gh_release "dawarich" "Freika/dawarich"; then if check_for_gh_release "dawarich" "Freika/dawarich"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop dawarich-web dawarich-worker systemctl stop dawarich-web dawarich-worker

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck # Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | Migration: MickLesk (CanbiZ) # Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dockge.kuma.pet/ # Source: https://dockge.kuma.pet/
@@ -19,45 +19,26 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh"
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /opt/dockge ]]; then if [[ ! -d /opt/dockge ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
msg_warn "⚠️ ${APP} has been migrated to an addon script." msg_info "Updating base system"
echo "" $STD apt update
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:" $STD apt upgrade -y
echo -e "${TAB}${TAB}${GN}update_dockge${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}" msg_ok "Base system updated"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
cd /opt/dockge
$STD docker compose pull
$STD docker compose up -d
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function" msg_info "Updating Dockge"
cat <<'MIGRATION_EOF' >/usr/bin/update cd /opt/dockge
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh)" $STD docker compose pull
MIGRATION_EOF $STD docker compose up -d
chmod +x /usr/bin/update msg_ok "Updated Dockge"
msg_ok "Updated successfully!"
ln -sf /usr/bin/update /usr/bin/update_dockge 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit exit
} }

View File

@@ -19,8 +19,6 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh"
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
@@ -31,31 +29,10 @@ function update_script() {
exit exit
fi fi
msg_warn "⚠️ ${APP} has been migrated to an addon script." msg_info "Updating Dokploy"
echo "" curl -sSL https://dokploy.com/install.sh | $STD bash -s update
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:" msg_ok "Updated Dokploy"
echo -e "${TAB}${TAB}${GN}update_dokploy${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}" msg_ok "Updated successfully!"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
curl -sSL https://dokploy.com/install.sh | $STD bash -s update
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_dokploy 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit exit
} }

View File

@@ -26,7 +26,7 @@ function update_script() {
if [[ ! -d /opt/endurain ]]; then if [[ ! -d /opt/endurain ]]; then
msg_error "No ${APP} installation found!" msg_error "No ${APP} installation found!"
exit 233 exit 1
fi fi
if check_for_gh_release "endurain" "endurain-project/endurain"; then if check_for_gh_release "endurain" "endurain-project/endurain"; then
msg_info "Stopping Service" msg_info "Stopping Service"

View File

@@ -25,7 +25,7 @@ function update_script() {
check_container_resources check_container_resources
if ! command -v evcc >/dev/null 2>&1; then if ! command -v evcc >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 233 exit 1
fi fi
if [[ -f /etc/apt/sources.list.d/evcc-stable.list ]]; then if [[ -f /etc/apt/sources.list.d/evcc-stable.list ]]; then

View File

@@ -26,7 +26,7 @@ function update_script() {
if ! dpkg -s grafana >/dev/null 2>&1; then if ! dpkg -s grafana >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 233 exit 1
fi fi
if [[ -f /etc/apt/sources.list.d/grafana.list ]] || [[ ! -f /etc/apt/sources.list.d/grafana.sources ]]; then if [[ -f /etc/apt/sources.list.d/grafana.list ]] || [[ ! -f /etc/apt/sources.list.d/grafana.sources ]]; then

View File

@@ -51,23 +51,11 @@ function update_script() {
cd /opt/gramps-web-api cd /opt/gramps-web-api
GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \ GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \
ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \ ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \
GRAMPSHOME=/opt/gramps-web/data \ GRAMPSHOME=/opt/gramps-web/data/gramps \
GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \ GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \
$STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate $STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate
msg_ok "Applied Database Migration" msg_ok "Applied Database Migration"
msg_info "Updating Gramps Addons"
GRAMPS_VERSION=$(/opt/gramps-web/venv/bin/python3 -c "import gramps.version; print('%s%s' % (gramps.version.VERSION_TUPLE[0], gramps.version.VERSION_TUPLE[1]))" 2>/dev/null || echo "60")
GRAMPS_PLUGINS_DIR="/opt/gramps-web/data/gramps/gramps${GRAMPS_VERSION}/plugins"
mkdir -p "$GRAMPS_PLUGINS_DIR"
$STD wget -q https://github.com/gramps-project/addons/archive/refs/heads/master.zip -O /tmp/gramps-addons.zip
for addon in FilterRules JSON; do
unzip -p /tmp/gramps-addons.zip "addons-master/gramps${GRAMPS_VERSION}/download/${addon}.addon.tgz" |
tar -xz -C "$GRAMPS_PLUGINS_DIR"
done
rm -f /tmp/gramps-addons.zip
msg_ok "Updated Gramps Addons"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start gramps-web systemctl start gramps-web
msg_ok "Started Service" msg_ok "Started Service"

View File

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

6
ct/headers/palmr Normal file
View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +0,0 @@
_______ __ __
/_ __(_)___ __ ______ ___ __/ /_/ /_
/ / / / __ \/ / / / __ `/ / / / __/ __ \
/ / / / / / / /_/ / /_/ / /_/ / /_/ / / /
/_/ /_/_/ /_/\__, /\__,_/\__,_/\__/_/ /_/
/____/

6
ct/headers/unifi Normal file
View File

@@ -0,0 +1,6 @@
__ __ _ _____
/ / / /___ (_) __(_)
/ / / / __ \/ / /_/ /
/ /_/ / / / / / __/ /
\____/_/ /_/_/_/ /_/

View File

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

View File

@@ -72,9 +72,9 @@ EOF
SOURCE_DIR=${STAGING_DIR}/image-source SOURCE_DIR=${STAGING_DIR}/image-source
cd /tmp cd /tmp
if [[ -f ~/.intel_version ]]; then if [[ -f ~/.intel_version ]]; then
curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile curl -fsSLO https://raw.githubusercontent.com/immich-app/base-images/refs/heads/main/server/Dockerfile
readarray -t INTEL_URLS < <( readarray -t INTEL_URLS < <(
sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $3}' sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $2}'
sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}' sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}'
) )
INTEL_RELEASE="$(grep "intel-opencl-icd_" ./Dockerfile | awk -F '_' '{print $2}')" INTEL_RELEASE="$(grep "intel-opencl-icd_" ./Dockerfile | awk -F '_' '{print $2}')"
@@ -97,7 +97,7 @@ EOF
if [[ -f ~/.immich_library_revisions ]]; then if [[ -f ~/.immich_library_revisions ]]; then
libraries=("libjxl" "libheif" "libraw" "imagemagick" "libvips") libraries=("libjxl" "libheif" "libraw" "imagemagick" "libvips")
cd "$BASE_DIR" cd "$BASE_DIR"
msg_warn "Checking for updates to custom image-processing libraries (recompile time: 2-15min per library)" msg_info "Checking for updates to custom image-processing libraries"
$STD git pull $STD git pull
for library in "${libraries[@]}"; do for library in "${libraries[@]}"; do
compile_"$library" compile_"$library"
@@ -214,9 +214,9 @@ EOF
export VIRTUAL_ENV="${ML_DIR}"/ml-venv export VIRTUAL_ENV="${ML_DIR}"/ml-venv
if [[ -f ~/.openvino ]]; then if [[ -f ~/.openvino ]]; then
msg_info "Updating HW-accelerated machine-learning" msg_info "Updating HW-accelerated machine-learning"
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p python3.13 --managed-python $STD uv add --no-sync --optional openvino onnxruntime-openvino==1.20.0 --active -n -p python3.12 --managed-python
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.13 --managed-python $STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.12 --managed-python
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-x86_64-linux-gnu.so" patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.12/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-312-x86_64-linux-gnu.so"
msg_ok "Updated HW-accelerated machine-learning" msg_ok "Updated HW-accelerated machine-learning"
else else
msg_info "Updating machine-learning" msg_info "Updating machine-learning"

View File

@@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Source: https://www.iobroker.net/#en/intro | Github: https://github.com/ioBroker/ioBroker.js-controller # Source: https://www.iobroker.net/#en/intro | Github: https://github.com/ioBroker/ioBroker.js-controller
APP="ioBroker" APP="ioBroker"
var_tags="${var_tags:-automation}" var_tags="${var_tags:-automtation}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}" var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}" var_disk="${var_disk:-8}"

View File

@@ -26,7 +26,7 @@ function update_script() {
if [[ ! -f /etc/itsm-ng/config_db.php ]]; then if [[ ! -f /etc/itsm-ng/config_db.php ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 233 exit 1
fi fi
setup_mariadb setup_mariadb

View File

@@ -28,7 +28,7 @@ function update_script() {
exit exit
fi fi
NODE_VERSION="24" NODE_MODULE="yarn,npm,pm2" setup_nodejs NODE_VERSION=24 NODE_MODULE="yarn,npm,pm2" setup_nodejs
if check_for_gh_release "joplin-server" "laurent22/joplin"; then if check_for_gh_release "joplin-server" "laurent22/joplin"; then
msg_info "Stopping Services" msg_info "Stopping Services"

View File

@@ -45,7 +45,7 @@ function update_script() {
if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then
msg_error "Unable to detect latest Kasm release URL." msg_error "Unable to detect latest Kasm release URL."
exit 250 exit 1
fi fi
msg_info "Checked for new version" msg_info "Checked for new version"

View File

@@ -1,79 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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/Chevron7Locked/kima-hub
APP="Kima-Hub"
var_tags="${var_tags:-music;streaming;media}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
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/kima-hub ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "kima-hub" "Chevron7Locked/kima-hub"; then
msg_info "Stopping Services"
systemctl stop kima-frontend kima-backend kima-analyzer kima-analyzer-clap
msg_ok "Stopped Services"
msg_info "Backing up Data"
cp /opt/kima-hub/backend/.env /opt/kima-hub-backend-env.bak
cp /opt/kima-hub/frontend/.env /opt/kima-hub-frontend-env.bak
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "kima-hub" "Chevron7Locked/kima-hub" "tarball"
msg_info "Restoring Data"
cp /opt/kima-hub-backend-env.bak /opt/kima-hub/backend/.env
cp /opt/kima-hub-frontend-env.bak /opt/kima-hub/frontend/.env
rm -f /opt/kima-hub-backend-env.bak /opt/kima-hub-frontend-env.bak
msg_ok "Restored Data"
msg_info "Rebuilding Backend"
cd /opt/kima-hub/backend
$STD npm install
$STD npm run build
$STD npx prisma generate
$STD npx prisma migrate deploy
msg_ok "Rebuilt Backend"
msg_info "Rebuilding Frontend"
cd /opt/kima-hub/frontend
$STD npm install
$STD npm run build
msg_ok "Rebuilt Frontend"
msg_info "Starting Services"
systemctl start kima-backend kima-frontend kima-analyzer kima-analyzer-clap
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}:3030${CL}"

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG # Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ) # Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do/ # Source: https://komo.do/
@@ -19,49 +19,49 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh"
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /opt/komodo ]]; then [[ -d /opt/komodo ]] || {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit 1
}
msg_info "Updating Komodo"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 1
fi
COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
if [[ "$COMPOSE_BASENAME" == "sqlite.compose.yaml" || "$COMPOSE_BASENAME" == "postgres.compose.yaml" ]]; then
msg_error "❌ Detected outdated Komodo setup using SQLite or PostgreSQL (FerretDB v1)."
echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}"
echo -e "${YW}Please follow the migration guide:${CL}"
echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n"
exit 1
fi fi
msg_warn "⚠️ ${APP} has been migrated to an addon script." BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
echo "" cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:" msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
echo -e "${TAB}${TAB}${GN}update_komodo${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}" exit 1
echo "" }
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_warn "Migration skipped. The old update will continue to work for now." msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
msg_info "Updating ${APP} (legacy)" mv "$BACKUP_FILE" "$COMPOSE_FILE"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1) exit 1
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 252
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated ${APP}"
exit
fi fi
if ! grep -qxF 'COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' /opt/komodo/compose.env; then
msg_info "Migrating update function" sed -i '/^COMPOSE_KOMODO_IMAGE_TAG=latest$/a COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' /opt/komodo/compose.env
cat <<'MIGRATION_EOF' >/usr/bin/update fi
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)" $STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
MIGRATION_EOF $STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
chmod +x /usr/bin/update msg_ok "Updated Komodo"
ln -sf /usr/bin/update /usr/bin/update_komodo 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit exit
} }

View File

@@ -26,7 +26,7 @@ function update_script() {
if ! dpkg -s loki >/dev/null 2>&1; then if ! dpkg -s loki >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit 233 exit 1
fi fi
CHOICE=$(msg_menu "Loki Update Options" \ CHOICE=$(msg_menu "Loki Update Options" \

View File

@@ -36,7 +36,6 @@ function update_script() {
[[ -f /opt/ombi/Ombi.db ]] && mv /opt/ombi/Ombi.db /opt [[ -f /opt/ombi/Ombi.db ]] && mv /opt/ombi/Ombi.db /opt
[[ -f /opt/ombi/OmbiExternal.db ]] && mv /opt/ombi/OmbiExternal.db /opt [[ -f /opt/ombi/OmbiExternal.db ]] && mv /opt/ombi/OmbiExternal.db /opt
[[ -f /opt/ombi/OmbiSettings.db ]] && mv /opt/ombi/OmbiSettings.db /opt [[ -f /opt/ombi/OmbiSettings.db ]] && mv /opt/ombi/OmbiSettings.db /opt
[[ -f /opt/ombi/database.json ]] && mv /opt/ombi/database.json /opt
msg_ok "Backup created" msg_ok "Backup created"
rm -rf /opt/ombi rm -rf /opt/ombi
@@ -44,7 +43,6 @@ function update_script() {
[[ -f /opt/Ombi.db ]] && mv /opt/Ombi.db /opt/ombi [[ -f /opt/Ombi.db ]] && mv /opt/Ombi.db /opt/ombi
[[ -f /opt/OmbiExternal.db ]] && mv /opt/OmbiExternal.db /opt/ombi [[ -f /opt/OmbiExternal.db ]] && mv /opt/OmbiExternal.db /opt/ombi
[[ -f /opt/OmbiSettings.db ]] && mv /opt/OmbiSettings.db /opt/ombi [[ -f /opt/OmbiSettings.db ]] && mv /opt/OmbiSettings.db /opt/ombi
[[ -f /opt/database.json ]] && mv /opt/database.json /opt/ombi
msg_info "Starting Service" msg_info "Starting Service"
systemctl start ombi systemctl start ombi

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}" var_ram="${var_ram:-4096}"
var_disk="${var_disk:-8}" var_disk="${var_disk:-8}"
var_os="${var_os:-debian}" var_os="${var_os:-debian}"
var_version="${var_version:-13}" var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}" var_unprivileged="${var_unprivileged:-1}"
header_info "$APP" header_info "$APP"
@@ -27,11 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
msg_info "Updating ${APP}"
msg_info "Updating OpenProject"
$STD apt update $STD apt update
$STD apt install --only-upgrade -y openproject $STD apt install --only-upgrade -y openproject
msg_ok "Updated OpenProject" msg_ok "Updated ${APP}"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
exit exit
} }

View File

@@ -28,7 +28,7 @@ function update_script() {
exit exit
fi fi
if [[ -f "$HOME/.overseerr" ]] && [[ "$(printf '%s\n' "1.35.0" "$(cat "$HOME/.overseerr")" | sort -V | head -n1)" == "1.35.0" ]]; then if [[ -f "$HOME/.overseerr" ]] && [[ "$(cat "$HOME/.overseerr")" == "1.34.0" ]]; then
echo echo
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Overseerr v1.34.0 detected." echo "Overseerr v1.34.0 detected."

75
ct/palmr.sh Normal file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/kyantech/Palmr
APP="Palmr"
var_tags="${var_tags:-files}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-6144}"
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/palmr_data ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "palmr" "kyantech/Palmr"; then
msg_info "Stopping Services"
systemctl stop palmr-frontend palmr-backend
msg_ok "Stopped Services"
cp /opt/palmr/apps/server/.env /opt/palmr.env
rm -rf /opt/palmr
fetch_and_deploy_gh_release "Palmr" "kyantech/Palmr" "tarball" "latest" "/opt/palmr"
PNPM="$(jq -r '.packageManager' /opt/palmr/package.json)"
NODE_VERSION="24" NODE_MODULE="$PNPM" setup_nodejs
msg_info "Updating ${APP}"
cd /opt/palmr/apps/server
mv /opt/palmr.env /opt/palmr/apps/server/.env
$STD pnpm install
$STD npx prisma generate
$STD npx prisma migrate deploy
$STD npx prisma db push
$STD pnpm build
cd /opt/palmr/apps/web
export NODE_ENV=production
export NEXT_TELEMETRY_DISABLED=1
mv ./.env.example ./.env
$STD pnpm install
$STD pnpm build
chown -R palmr:palmr /opt/palmr_data /opt/palmr
msg_ok "Updated ${APP}"
msg_info "Starting Services"
systemctl start palmr-backend palmr-frontend
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}"

View File

@@ -9,7 +9,7 @@ APP="Pangolin"
var_tags="${var_tags:-proxy}" var_tags="${var_tags:-proxy}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}" var_ram="${var_ram:-4096}"
var_disk="${var_disk:-10}" var_disk="${var_disk:-5}"
var_os="${var_os:-debian}" var_os="${var_os:-debian}"
var_version="${var_version:-13}" var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}" var_unprivileged="${var_unprivileged:-1}"
@@ -29,8 +29,6 @@ function update_script() {
exit exit
fi fi
ensure_dependencies build-essential python3
NODE_VERSION="24" setup_nodejs NODE_VERSION="24" setup_nodejs
if check_for_gh_release "pangolin" "fosrl/pangolin"; then if check_for_gh_release "pangolin" "fosrl/pangolin"; then

View File

@@ -44,7 +44,7 @@ function update_script() {
echo -e "${TAB}${GATEWAY}${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/9223${CL}" echo -e "${TAB}${GATEWAY}${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/9223${CL}"
echo -e "" echo -e ""
msg_custom "⚠️" "Update aborted. Please migrate your data first." msg_custom "⚠️" "Update aborted. Please migrate your data first."
exit 253 exit 1
fi fi
fi fi

View File

@@ -51,10 +51,13 @@ function update_script() {
msg_info "Updating PatchMon" msg_info "Updating PatchMon"
VERSION=$(get_latest_github_release "PatchMon/PatchMon") VERSION=$(get_latest_github_release "PatchMon/PatchMon")
PROTO="$(sed -n '/SERVER_PROTOCOL/s/[^=]*=//p' /opt/backend.env)"
HOST="$(sed -n '/SERVER_HOST/s/[^=]*=//p' /opt/backend.env)"
SERVER_PORT="$(sed -n '/SERVER_PORT/s/[^=]*=//p' /opt/backend.env)" SERVER_PORT="$(sed -n '/SERVER_PORT/s/[^=]*=//p' /opt/backend.env)"
[[ "$PROTO" == "http" ]] && PORT=":3001"
sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env
sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \ sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \
-e '/^VITE_API_URL/d' /opt/frontend.env -e "\|VITE_API_URL=|s|http.*|${PROTO:-http}://${HOST:-$LOCAL_IP}${PORT:-}/api/v1|" /opt/frontend.env
export NODE_ENV=production export NODE_ENV=production
cd /opt/patchmon cd /opt/patchmon
$STD npm install --no-audit --no-fund --no-save --ignore-scripts $STD npm install --no-audit --no-fund --no-save --ignore-scripts

View File

@@ -1,68 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://www.powerdns.com/
APP="PowerDNS"
var_tags="${var_tags:-dns}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
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/poweradmin ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating PowerDNS"
$STD apt update
$STD apt install -y --only-upgrade pdns-server pdns-backend-sqlite3
msg_ok "Updated PowerDNS"
if check_for_gh_release "poweradmin" "poweradmin/poweradmin"; then
msg_info "Backing up Configuration"
cp /opt/poweradmin/config/settings.php /opt/poweradmin_settings.php.bak
cp /opt/poweradmin/powerdns.db /opt/poweradmin_powerdns.db.bak
msg_ok "Backed up Configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "poweradmin" "poweradmin/poweradmin" "tarball"
msg_info "Updating Poweradmin"
cp /opt/poweradmin_settings.php.bak /opt/poweradmin/config/settings.php
cp /opt/poweradmin_powerdns.db.bak /opt/poweradmin/powerdns.db
rm -rf /opt/poweradmin/install
rm -f /opt/poweradmin_settings.php.bak /opt/poweradmin_powerdns.db.bak
chown -R www-data:www-data /opt/poweradmin
msg_ok "Updated Poweradmin"
msg_info "Restarting Services"
systemctl restart pdns apache2
msg_ok "Restarted Services"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@@ -1,85 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Dictionarry-Hub/profilarr
APP="Profilarr"
var_tags="${var_tags:-arr;radarr;sonarr;config}"
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 [[ ! -d /opt/profilarr ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "profilarr" "Dictionarry-Hub/profilarr"; then
msg_info "Stopping Service"
systemctl stop profilarr
msg_ok "Stopped Service"
msg_info "Backing up Data"
if [[ -d /config ]]; then
cp -r /config /opt/profilarr_config_backup
fi
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "profilarr" "Dictionarry-Hub/profilarr" "tarball"
msg_info "Installing Python Dependencies"
cd /opt/profilarr/backend
$STD uv venv /opt/profilarr/backend/.venv
sed 's/==/>=/g' requirements.txt >requirements-relaxed.txt
$STD uv pip install --python /opt/profilarr/backend/.venv/bin/python -r requirements-relaxed.txt
rm -f requirements-relaxed.txt
msg_ok "Installed Python Dependencies"
msg_info "Building Frontend"
if [[ -d /opt/profilarr/frontend ]]; then
cd /opt/profilarr/frontend
$STD npm install
$STD npm run build
cp -r dist /opt/profilarr/backend/app/static
fi
msg_ok "Built Frontend"
msg_info "Restoring Data"
if [[ -d /opt/profilarr_config_backup ]]; then
mkdir -p /config
cp -r /opt/profilarr_config_backup/. /config/
rm -rf /opt/profilarr_config_backup
fi
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start profilarr
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}:6868${CL}"

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck # Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) | Migration: MickLesk (CanbiZ) # Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://runtipi.io/ # Source: https://runtipi.io/
@@ -19,43 +19,16 @@ variables
color color
catch_errors catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh"
function update_script() { function update_script() {
header_info header_info
check_container_storage check_container_storage
check_container_resources check_container_resources
if [[ ! -d /opt/runtipi ]]; then if [[ ! -d /opt/runtipi ]]; then
msg_error "No ${APP} Installation Found!" msg_error "No ${APP} Installation Found!"
exit exit
fi fi
cd /opt/runtipi && ./runtipi-cli update latest
msg_warn "⚠️ ${APP} has been migrated to an addon script." msg_ok "Updated successfully!"
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_runtipi${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
cd /opt/runtipi && ./runtipi-cli update latest
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_runtipi 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit exit
} }

View File

@@ -52,6 +52,7 @@ function update_script() {
systemctl start searxng systemctl start searxng
msg_ok "Started Services" msg_ok "Started Services"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi
exit exit
} }
start start

View File

@@ -29,6 +29,8 @@ function update_script() {
exit exit
fi fi
NODE_VERSION="25" setup_nodejs
if check_for_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness"; then if check_for_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop sparkyfitness-server nginx systemctl stop sparkyfitness-server nginx
@@ -46,9 +48,6 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness" "tarball"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1]' /opt/sparkyfitness/package.json)"
NODE_VERSION="25" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
msg_info "Updating Sparky Fitness Backend" msg_info "Updating Sparky Fitness Backend"
cd /opt/sparkyfitness/SparkyFitnessServer cd /opt/sparkyfitness/SparkyFitnessServer
$STD npm install $STD npm install
@@ -56,8 +55,8 @@ function update_script() {
msg_info "Updating Sparky Fitness Frontend (Patience)" msg_info "Updating Sparky Fitness Frontend (Patience)"
cd /opt/sparkyfitness/SparkyFitnessFrontend cd /opt/sparkyfitness/SparkyFitnessFrontend
$STD pnpm install $STD npm install
$STD pnpm run build $STD npm run build
cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/ cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/
msg_ok "Updated Sparky Fitness Frontend" msg_ok "Updated Sparky Fitness Frontend"

View File

@@ -1,61 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: pespinel
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://strapi.io/
APP="Strapi"
var_tags="${var_tags:-cms}"
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}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/strapi.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
NODE_VERSION="24" setup_nodejs
msg_info "Stopping Strapi"
systemctl stop strapi
msg_ok "Stopped Strapi"
msg_info "Updating Strapi"
cd /opt/strapi
$STD npx @strapi/upgrade minor --yes
msg_ok "Updated Strapi"
msg_info "Building Strapi"
export NODE_OPTIONS="--max-old-space-size=3072"
$STD npm run build
msg_ok "Built Strapi"
msg_info "Starting Strapi"
systemctl start strapi
msg_ok "Started Strapi"
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}:1337${CL}"

View File

@@ -1,53 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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/steveiliop56/tinyauth
APP="Tinyauth"
var_tags="${var_tags:-auth}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/tinyauth ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "tinyauth" "steveiliop56/tinyauth"; then
msg_info "Stopping Service"
systemctl stop tinyauth
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "tinyauth" "steveiliop56/tinyauth" "singlefile" "latest" "/opt/tinyauth" "tinyauth-amd64"
msg_info "Starting Service"
systemctl start tinyauth
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}"

View File

@@ -75,31 +75,10 @@ if [ -f \$pg_config_file ]; then
fi fi
fi fi
systemctl restart postgresql systemctl restart postgresql
sudo -u postgres psql -c "ALTER USER tracearr WITH SUPERUSER;"
EOF EOF
chmod +x /data/tracearr/prestart.sh chmod +x /data/tracearr/prestart.sh
msg_ok "Updated prestart script" msg_ok "Updated prestart script"
# check if tailscale is installed
if command -v tailscale >/dev/null 2>&1; then
# Tracearr runs tailscaled in user mode, disable the service.
$STD systemctl disable --now tailscaled
$STD systemctl stop tailscaled
msg_ok "Tailscale already installed"
else
msg_info "Installing tailscale"
setup_deb822_repo \
"tailscale" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/$(get_os_info codename).noarmor.gpg" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/" \
"$(get_os_info codename)"
$STD apt install -y tailscale
# Tracearr runs tailscaled in user mode, disable the service.
$STD systemctl disable --now tailscaled
$STD systemctl stop tailscaled
msg_ok "Installed tailscale"
fi
if check_for_gh_release "tracearr" "connorgallopo/Tracearr"; then if check_for_gh_release "tracearr" "connorgallopo/Tracearr"; then
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop tracearr postgresql redis systemctl stop tracearr postgresql redis
@@ -143,8 +122,6 @@ EOF
sed -i "s/^APP_VERSION=.*/APP_VERSION=$(cat /root/.tracearr)/" /data/tracearr/.env sed -i "s/^APP_VERSION=.*/APP_VERSION=$(cat /root/.tracearr)/" /data/tracearr/.env
chmod 600 /data/tracearr/.env chmod 600 /data/tracearr/.env
chown -R tracearr:tracearr /data/tracearr chown -R tracearr:tracearr /data/tracearr
mkdir -p /data/backup
chown -R tracearr:tracearr /data/backup
msg_ok "Configured Tracearr" msg_ok "Configured Tracearr"
msg_info "Starting services" msg_info "Starting services"

47
ct/unifi.sh Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/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://ui.com/download/unifi
APP="Unifi"
var_tags="${var_tags:-network;unifi}"
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}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /usr/lib/unifi ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
JAVA_VERSION="21" setup_java
msg_info "Updating ${APP}"
$STD apt update --allow-releaseinfo-change
ensure_dependencies unifi
msg_ok "Updated successfully!"
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8443${CL}"

View File

@@ -34,14 +34,14 @@ function update_script() {
msg_warn "This requires MANUAL config changes in /etc/vikunja/config.yml." msg_warn "This requires MANUAL config changes in /etc/vikunja/config.yml."
msg_warn "See: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes" msg_warn "See: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes"
read -rp "Continue with update? (y to proceed): " -t 30 CONFIRM1 || exit 254 read -rp "Continue with update? (y to proceed): " -t 30 CONFIRM1 || exit 1
[[ "$CONFIRM1" =~ ^[yY]$ ]] || exit 0 [[ "$CONFIRM1" =~ ^[yY]$ ]] || exit 0
echo echo
msg_warn "Vikunja may not start after the update until you manually adjust the config." msg_warn "Vikunja may not start after the update until you manually adjust the config."
msg_warn "Details: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes" msg_warn "Details: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes"
read -rp "Acknowledge and continue? (y): " -t 30 CONFIRM2 || exit 254 read -rp "Acknowledge and continue? (y): " -t 30 CONFIRM2 || exit 1
[[ "$CONFIRM2" =~ ^[yY]$ ]] || exit 0 [[ "$CONFIRM2" =~ ^[yY]$ ]] || exit 0
fi fi
@@ -65,7 +65,6 @@ function update_script() {
msg_ok "Stopped Service" msg_ok "Stopped Service"
fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary" fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary"
$STD systemctl daemon-reload
msg_info "Starting Service" msg_info "Starting Service"
systemctl start vikunja systemctl start vikunja

View File

@@ -43,15 +43,16 @@ function update_script() {
msg_info "Building Frontend (patience)" msg_info "Building Frontend (patience)"
cd /opt/wealthfolio cd /opt/wealthfolio
export BUILD_TARGET=web
$STD pnpm install --frozen-lockfile $STD pnpm install --frozen-lockfile
$STD pnpm --filter frontend... build $STD pnpm tsc
$STD pnpm vite build
msg_ok "Built Frontend" msg_ok "Built Frontend"
msg_info "Building Backend (patience)" msg_info "Building Backend (patience)"
cd /opt/wealthfolio/src-server
source ~/.cargo/env source ~/.cargo/env
$STD cargo build --release --manifest-path apps/server/Cargo.toml $STD cargo build --release --manifest-path Cargo.toml
cp /opt/wealthfolio/target/release/wealthfolio-server /usr/local/bin/wealthfolio-server cp /opt/wealthfolio/src-server/target/release/wealthfolio-server /usr/local/bin/wealthfolio-server
chmod +x /usr/local/bin/wealthfolio-server chmod +x /usr/local/bin/wealthfolio-server
msg_ok "Built Backend" msg_ok "Built Backend"
@@ -62,7 +63,7 @@ function update_script() {
msg_ok "Restored Data" msg_ok "Restored Data"
msg_info "Cleaning Up" msg_info "Cleaning Up"
rm -rf /opt/wealthfolio/target rm -rf /opt/wealthfolio/src-server/target
rm -rf /root/.cargo/registry rm -rf /root/.cargo/registry
rm -rf /opt/wealthfolio/node_modules rm -rf /opt/wealthfolio/node_modules
msg_ok "Cleaned Up" msg_ok "Cleaned Up"

View File

@@ -1,71 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: community-scripts
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/nicotsx/zerobyte
APP="Zerobyte"
var_tags="${var_tags:-backup;encryption;restic}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-6144}"
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/zerobyte ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "zerobyte" "nicotsx/zerobyte"; then
msg_info "Stopping Service"
systemctl stop zerobyte
msg_ok "Stopped Service"
msg_info "Backing up Configuration"
cp /opt/zerobyte/.env /opt/zerobyte.env.bak
msg_ok "Backed up Configuration"
NODE_VERSION="24" setup_nodejs
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "zerobyte" "nicotsx/zerobyte" "tarball"
msg_info "Building Zerobyte"
export NODE_OPTIONS="--max-old-space-size=3072"
cd /opt/zerobyte
$STD bun install
$STD node ./node_modules/vite/bin/vite.js build
msg_ok "Built Zerobyte"
msg_info "Restoring Configuration"
cp /opt/zerobyte.env.bak /opt/zerobyte/.env
rm -f /opt/zerobyte.env.bak
msg_ok "Restored Configuration"
msg_info "Starting Service"
systemctl start zerobyte
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}:4096${CL}"

View File

@@ -29,7 +29,7 @@ function update_script() {
fi fi
if check_for_gh_release "Zigbee2MQTT" "Koenkk/zigbee2mqtt"; then if check_for_gh_release "Zigbee2MQTT" "Koenkk/zigbee2mqtt"; then
NODE_VERSION="24" NODE_MODULE="pnpm@$(curl -fsSL https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/master/package.json | jq -r '.packageManager | split("@")[1]')" setup_nodejs NODE_VERSION=24 NODE_MODULE="pnpm@$(curl -fsSL https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/master/package.json | jq -r '.packageManager | split("@")[1]')" setup_nodejs
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop zigbee2mqtt systemctl stop zigbee2mqtt
msg_ok "Stopped Service" msg_ok "Stopped Service"

View File

@@ -175,7 +175,7 @@ All scripts and configurations must follow our coding standards to ensure consis
### Available Guides ### Available Guides
- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Essential coding standards and best practices - **[CONTRIBUTING.md](CONTRIBUTING.md)** - Essential coding standards and best practices
- **[CODE-AUDIT.md](CODE-AUDIT.md)** - Code review checklist and audit procedures - **[CODE_AUDIT.md](CODE_AUDIT.md)** - Code review checklist and audit procedures
- **[GUIDE.md](GUIDE.md)** - Comprehensive contribution guide - **[GUIDE.md](GUIDE.md)** - Comprehensive contribution guide
- **[HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md)** - Reference for all tools.func helper functions - **[HELPER_FUNCTIONS.md](HELPER_FUNCTIONS.md)** - Reference for all tools.func helper functions
- **Container Scripts** - `/ct/` templates and guidelines - **Container Scripts** - `/ct/` templates and guidelines

View File

@@ -1,10 +1,10 @@
{ {
"name": "Tinyauth", "name": "Alpine-Tinyauth",
"slug": "tinyauth", "slug": "alpine-tinyauth",
"categories": [ "categories": [
6 6
], ],
"date_created": "2026-03-03", "date_created": "2025-05-06",
"type": "ct", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
@@ -17,13 +17,13 @@
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "ct/tinyauth.sh", "script": "ct/alpine-tinyauth.sh",
"resources": { "resources": {
"cpu": 1, "cpu": 1,
"ram": 512, "ram": 256,
"hdd": 4, "hdd": 2,
"os": "debian", "os": "alpine",
"version": "13" "version": "3.23"
} }
}, },
{ {

View File

@@ -1,56 +1,52 @@
{ {
"name": "Coolify", "name": "Coolify",
"slug": "coolify", "slug": "coolify",
"categories": [ "categories": [
3 3
], ],
"date_created": "2025-12-09", "date_created": "2025-12-09",
"type": "addon", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": 8000, "interface_port": 8000,
"documentation": "https://coolify.io/docs", "documentation": "https://coolify.io/docs",
"website": "https://coolify.io/", "config_path": "/data/coolify",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/coolify.webp", "website": "https://coolify.io/",
"config_path": "/data/coolify", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/coolify.webp",
"description": "Coolify is an open-source & self-hostable alternative to Heroku, Netlify, and Vercel. It helps you manage your servers, applications, and databases on your own hardware with Docker. Deploy any application from Git repositories, Docker images, or use pre-built templates.", "description": "Coolify is an open-source & self-hostable alternative to Heroku, Netlify, and Vercel. It helps you manage your servers, applications, and databases on your own hardware with Docker. Deploy any application from Git repositories, Docker images, or use pre-built templates.",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "tools/addon/coolify.sh", "script": "ct/coolify.sh",
"resources": { "resources": {
"cpu": null, "cpu": 2,
"ram": null, "ram": 4096,
"hdd": null, "hdd": 30,
"os": null, "os": "Debian",
"version": null "version": "13"
} }
} }
], ],
"default_credentials": { "default_credentials": {
"username": null, "username": null,
"password": null "password": null
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
}, },
{ "notes": [
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)", {
"type": "info" "text": "Initial setup will be done via the web interface on first access.",
}, "type": "info"
{ },
"text": "Initial setup will be done via the web interface on first access.", {
"type": "info" "text": "Coolify has built-in auto-updates. You can configure update frequency in Settings.",
}, "type": "info"
{ },
"text": "Coolify has built-in auto-updates. You can configure update frequency in Settings.", {
"type": "info" "text": "Coolify requires SSH access to manage deployments. SSH is enabled automatically.",
}, "type": "info"
{ },
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh)", {
"type": "info" "text": "This container uses Docker-in-Docker (nesting) for application deployments.",
} "type": "warning"
] }
]
} }

View File

@@ -5,25 +5,25 @@
3 3
], ],
"date_created": "2024-05-02", "date_created": "2024-05-02",
"type": "addon", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": 5001, "interface_port": 5001,
"documentation": null, "documentation": null,
"website": "https://github.com/louislam/dockge", "website": "https://github.com/louislam/dockge",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/dockge.webp", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/dockge.webp",
"config_path": "/opt/dockge/compose.yaml", "config_path": "",
"description": "Dockge is a fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager.", "description": "Dockge is a fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager.",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "tools/addon/dockge.sh", "script": "ct/dockge.sh",
"resources": { "resources": {
"cpu": null, "cpu": 2,
"ram": null, "ram": 2048,
"hdd": null, "hdd": 18,
"os": null, "os": "debian",
"version": null "version": "13"
} }
} }
], ],
@@ -33,16 +33,12 @@
}, },
"notes": [ "notes": [
{ {
"text": "This is an addon script intended to be used on top of an existing Docker container.", "text": "Options to add Immich and/or Home Assistant",
"type": "info" "type": "info"
}, },
{ {
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)", "text": "If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"type": "info" "type": "warning"
},
{
"text": "To update, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh)",
"type": "info"
} }
] ]
} }

View File

@@ -1,56 +1,48 @@
{ {
"name": "Dokploy", "name": "Dokploy",
"slug": "dokploy", "slug": "dokploy",
"categories": [ "categories": [
3 3
], ],
"date_created": "2025-12-09", "date_created": "2025-12-09",
"type": "addon", "type": "ct",
"updateable": true, "updateable": true,
"privileged": true, "privileged": true,
"interface_port": 3000, "interface_port": 3000,
"documentation": "https://docs.dokploy.com/", "documentation": "https://docs.dokploy.com/",
"website": "https://dokploy.com/", "config_path": "/etc/dokploy",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/dokploy.png", "website": "https://dokploy.com/",
"config_path": "/etc/dokploy", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/dokploy.png",
"description": "Dokploy is a free, self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases. Built with Docker and Traefik, it offers features like automatic SSL, Docker Compose support, database backups, and a real-time monitoring dashboard.", "description": "Dokploy is a free, self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases. Built with Docker and Traefik, it offers features like automatic SSL, Docker Compose support, database backups, and a real-time monitoring dashboard.",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "tools/addon/dokploy.sh", "script": "ct/dokploy.sh",
"resources": { "resources": {
"cpu": null, "cpu": 2,
"ram": null, "ram": 2048,
"hdd": null, "hdd": 10,
"os": null, "os": "Debian",
"version": null "version": "13"
} }
} }
], ],
"default_credentials": { "default_credentials": {
"username": null, "username": null,
"password": null "password": null
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
}, },
{ "notes": [
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)", {
"type": "info" "text": "Initial setup will be done via the web interface on first access.",
}, "type": "info"
{ },
"text": "Initial setup will be done via the web interface on first access.", {
"type": "info" "text": "Dokploy has built-in auto-updates via the web interface.",
}, "type": "info"
{ },
"text": "Dokploy has built-in auto-updates via the web interface.", {
"type": "info" "text": "This container uses Docker-in-Docker (nesting) for application deployments.",
}, "type": "warning"
{ }
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh)", ]
"type": "info"
}
]
} }

View File

@@ -1,5 +1,5 @@
{ {
"generated": "2026-03-03T12:12:16Z", "generated": "2026-02-24T12:15:44Z",
"versions": [ "versions": [
{ {
"slug": "2fauth", "slug": "2fauth",
@@ -18,9 +18,9 @@
{ {
"slug": "adguardhome-sync", "slug": "adguardhome-sync",
"repo": "bakito/adguardhome-sync", "repo": "bakito/adguardhome-sync",
"version": "v0.9.0", "version": "v0.8.2",
"pinned": false, "pinned": false,
"date": "2026-02-27T18:37:37Z" "date": "2025-10-24T17:13:47Z"
}, },
{ {
"slug": "adventurelog", "slug": "adventurelog",
@@ -39,9 +39,9 @@
{ {
"slug": "ampache", "slug": "ampache",
"repo": "ampache/ampache", "repo": "ampache/ampache",
"version": "7.9.1", "version": "7.9.0",
"pinned": false, "pinned": false,
"date": "2026-02-25T08:52:58Z" "date": "2026-02-19T07:01:25Z"
}, },
{ {
"slug": "argus", "slug": "argus",
@@ -109,16 +109,16 @@
{ {
"slug": "bazarr", "slug": "bazarr",
"repo": "morpheus65535/bazarr", "repo": "morpheus65535/bazarr",
"version": "v1.5.6", "version": "v1.5.5",
"pinned": false, "pinned": false,
"date": "2026-02-26T11:33:11Z" "date": "2026-02-01T18:00:34Z"
}, },
{ {
"slug": "bentopdf", "slug": "bentopdf",
"repo": "alam00000/bentopdf", "repo": "alam00000/bentopdf",
"version": "v2.4.0", "version": "v2.3.1",
"pinned": false, "pinned": false,
"date": "2026-03-01T14:25:43Z" "date": "2026-02-21T09:04:27Z"
}, },
{ {
"slug": "beszel", "slug": "beszel",
@@ -144,23 +144,23 @@
{ {
"slug": "blocky", "slug": "blocky",
"repo": "0xERR0R/blocky", "repo": "0xERR0R/blocky",
"version": "v0.29.0", "version": "v0.28.2",
"pinned": false, "pinned": false,
"date": "2026-02-27T15:48:56Z" "date": "2025-11-18T05:51:46Z"
}, },
{ {
"slug": "booklore", "slug": "booklore",
"repo": "booklore-app/BookLore", "repo": "booklore-app/BookLore",
"version": "v2.0.5", "version": "v2.0.1",
"pinned": false, "pinned": false,
"date": "2026-03-01T16:13:13Z" "date": "2026-02-24T04:15:33Z"
}, },
{ {
"slug": "bookstack", "slug": "bookstack",
"repo": "BookStackApp/BookStack", "repo": "BookStackApp/BookStack",
"version": "v25.12.8", "version": "v25.12.7",
"pinned": false, "pinned": false,
"date": "2026-02-27T10:33:14Z" "date": "2026-02-19T23:36:55Z"
}, },
{ {
"slug": "byparr", "slug": "byparr",
@@ -200,9 +200,9 @@
{ {
"slug": "cleanuparr", "slug": "cleanuparr",
"repo": "Cleanuparr/Cleanuparr", "repo": "Cleanuparr/Cleanuparr",
"version": "v2.7.7", "version": "v2.7.4",
"pinned": false, "pinned": false,
"date": "2026-03-02T13:08:32Z" "date": "2026-02-23T18:41:16Z"
}, },
{ {
"slug": "cloudreve", "slug": "cloudreve",
@@ -214,9 +214,9 @@
{ {
"slug": "comfyui", "slug": "comfyui",
"repo": "comfyanonymous/ComfyUI", "repo": "comfyanonymous/ComfyUI",
"version": "v0.15.1", "version": "v0.14.2",
"pinned": false, "pinned": false,
"date": "2026-02-26T22:01:35Z" "date": "2026-02-18T06:12:02Z"
}, },
{ {
"slug": "commafeed", "slug": "commafeed",
@@ -242,9 +242,9 @@
{ {
"slug": "cosmos", "slug": "cosmos",
"repo": "azukaar/Cosmos-Server", "repo": "azukaar/Cosmos-Server",
"version": "v0.21.6", "version": "v0.20.2",
"pinned": false, "pinned": false,
"date": "2026-02-28T22:00:49Z" "date": "2026-01-24T00:12:39Z"
}, },
{ {
"slug": "cronicle", "slug": "cronicle",
@@ -270,16 +270,16 @@
{ {
"slug": "databasus", "slug": "databasus",
"repo": "databasus/databasus", "repo": "databasus/databasus",
"version": "v3.16.4", "version": "v3.16.2",
"pinned": false, "pinned": false,
"date": "2026-03-01T08:20:17Z" "date": "2026-02-22T21:10:12Z"
}, },
{ {
"slug": "dawarich", "slug": "dawarich",
"repo": "Freika/dawarich", "repo": "Freika/dawarich",
"version": "1.3.1", "version": "1.2.0",
"pinned": false, "pinned": false,
"date": "2026-02-27T19:47:40Z" "date": "2026-02-15T22:33:56Z"
}, },
{ {
"slug": "discopanel", "slug": "discopanel",
@@ -291,9 +291,9 @@
{ {
"slug": "dispatcharr", "slug": "dispatcharr",
"repo": "Dispatcharr/Dispatcharr", "repo": "Dispatcharr/Dispatcharr",
"version": "v0.20.2", "version": "v0.19.0",
"pinned": false, "pinned": false,
"date": "2026-03-03T01:40:33Z" "date": "2026-02-10T21:18:10Z"
}, },
{ {
"slug": "docmost", "slug": "docmost",
@@ -312,9 +312,9 @@
{ {
"slug": "domain-monitor", "slug": "domain-monitor",
"repo": "Hosteroid/domain-monitor", "repo": "Hosteroid/domain-monitor",
"version": "v1.1.4", "version": "v1.1.3",
"pinned": false, "pinned": false,
"date": "2026-03-02T09:25:01Z" "date": "2026-02-11T15:48:18Z"
}, },
{ {
"slug": "donetick", "slug": "donetick",
@@ -361,16 +361,16 @@
{ {
"slug": "endurain", "slug": "endurain",
"repo": "endurain-project/endurain", "repo": "endurain-project/endurain",
"version": "v0.17.6", "version": "v0.17.4",
"pinned": false, "pinned": false,
"date": "2026-02-27T23:08:50Z" "date": "2026-02-11T04:54:22Z"
}, },
{ {
"slug": "ersatztv", "slug": "ersatztv",
"repo": "ErsatzTV/ErsatzTV", "repo": "ErsatzTV/ErsatzTV",
"version": "v26.3.0", "version": "v26.2.0",
"pinned": false, "pinned": false,
"date": "2026-02-24T21:36:34Z" "date": "2026-02-02T20:54:26Z"
}, },
{ {
"slug": "excalidraw", "slug": "excalidraw",
@@ -382,9 +382,9 @@
{ {
"slug": "firefly", "slug": "firefly",
"repo": "firefly-iii/firefly-iii", "repo": "firefly-iii/firefly-iii",
"version": "v6.5.2", "version": "v6.5.0",
"pinned": false, "pinned": false,
"date": "2026-03-03T05:42:27Z" "date": "2026-02-23T19:19:00Z"
}, },
{ {
"slug": "fladder", "slug": "fladder",
@@ -424,9 +424,9 @@
{ {
"slug": "frigate", "slug": "frigate",
"repo": "blakeblackshear/frigate", "repo": "blakeblackshear/frigate",
"version": "v0.17.0", "version": "v0.16.4",
"pinned": true, "pinned": true,
"date": "2026-02-27T03:03:01Z" "date": "2026-01-29T00:42:14Z"
}, },
{ {
"slug": "gatus", "slug": "gatus",
@@ -438,9 +438,9 @@
{ {
"slug": "ghostfolio", "slug": "ghostfolio",
"repo": "ghostfolio/ghostfolio", "repo": "ghostfolio/ghostfolio",
"version": "2.245.0", "version": "2.243.0",
"pinned": false, "pinned": false,
"date": "2026-03-01T09:09:57Z" "date": "2026-02-23T19:31:36Z"
}, },
{ {
"slug": "gitea", "slug": "gitea",
@@ -452,9 +452,9 @@
{ {
"slug": "gitea-mirror", "slug": "gitea-mirror",
"repo": "RayLabsHQ/gitea-mirror", "repo": "RayLabsHQ/gitea-mirror",
"version": "v3.11.0", "version": "v3.9.4",
"pinned": false, "pinned": false,
"date": "2026-03-02T10:19:59Z" "date": "2026-02-24T06:17:56Z"
}, },
{ {
"slug": "glance", "slug": "glance",
@@ -480,9 +480,9 @@
{ {
"slug": "gotify", "slug": "gotify",
"repo": "gotify/server", "repo": "gotify/server",
"version": "v2.9.1", "version": "v2.9.0",
"pinned": false, "pinned": false,
"date": "2026-02-28T19:07:07Z" "date": "2026-02-13T15:22:31Z"
}, },
{ {
"slug": "gramps-web", "slug": "gramps-web",
@@ -494,9 +494,9 @@
{ {
"slug": "grist", "slug": "grist",
"repo": "gristlabs/grist-core", "repo": "gristlabs/grist-core",
"version": "v1.7.11", "version": "v1.7.10",
"pinned": false, "pinned": false,
"date": "2026-02-27T17:13:50Z" "date": "2026-01-12T20:50:50Z"
}, },
{ {
"slug": "grocy", "slug": "grocy",
@@ -550,9 +550,9 @@
{ {
"slug": "homarr", "slug": "homarr",
"repo": "homarr-labs/homarr", "repo": "homarr-labs/homarr",
"version": "v1.54.0", "version": "v1.53.2",
"pinned": false, "pinned": false,
"date": "2026-02-27T19:38:50Z" "date": "2026-02-20T19:41:55Z"
}, },
{ {
"slug": "homebox", "slug": "homebox",
@@ -585,9 +585,9 @@
{ {
"slug": "immich-public-proxy", "slug": "immich-public-proxy",
"repo": "alangrainger/immich-public-proxy", "repo": "alangrainger/immich-public-proxy",
"version": "v1.15.4", "version": "v1.15.3",
"pinned": false, "pinned": false,
"date": "2026-03-02T21:28:06Z" "date": "2026-02-16T22:54:27Z"
}, },
{ {
"slug": "inspircd", "slug": "inspircd",
@@ -606,16 +606,16 @@
{ {
"slug": "invoiceninja", "slug": "invoiceninja",
"repo": "invoiceninja/invoiceninja", "repo": "invoiceninja/invoiceninja",
"version": "v5.12.69", "version": "v5.12.66",
"pinned": false, "pinned": false,
"date": "2026-02-26T22:23:32Z" "date": "2026-02-24T09:12:50Z"
}, },
{ {
"slug": "jackett", "slug": "jackett",
"repo": "Jackett/Jackett", "repo": "Jackett/Jackett",
"version": "v0.24.1261", "version": "v0.24.1193",
"pinned": false, "pinned": false,
"date": "2026-03-03T05:54:20Z" "date": "2026-02-24T05:58:04Z"
}, },
{ {
"slug": "jellystat", "slug": "jellystat",
@@ -627,16 +627,16 @@
{ {
"slug": "joplin-server", "slug": "joplin-server",
"repo": "laurent22/joplin", "repo": "laurent22/joplin",
"version": "v3.5.13", "version": "v3.5.12",
"pinned": false, "pinned": false,
"date": "2026-02-25T21:19:11Z" "date": "2026-01-17T14:20:33Z"
}, },
{ {
"slug": "jotty", "slug": "jotty",
"repo": "fccview/jotty", "repo": "fccview/jotty",
"version": "1.21.0", "version": "1.20.0",
"pinned": false, "pinned": false,
"date": "2026-03-02T11:08:54Z" "date": "2026-02-12T09:23:30Z"
}, },
{ {
"slug": "kapowarr", "slug": "kapowarr",
@@ -666,19 +666,12 @@
"pinned": false, "pinned": false,
"date": "2026-02-20T09:19:45Z" "date": "2026-02-20T09:19:45Z"
}, },
{
"slug": "kima-hub",
"repo": "Chevron7Locked/kima-hub",
"version": "v1.6.0",
"pinned": false,
"date": "2026-03-02T05:43:31Z"
},
{ {
"slug": "kimai", "slug": "kimai",
"repo": "kimai/kimai", "repo": "kimai/kimai",
"version": "2.51.0", "version": "2.49.0",
"pinned": false, "pinned": false,
"date": "2026-03-01T15:56:56Z" "date": "2026-02-15T20:40:19Z"
}, },
{ {
"slug": "kitchenowl", "slug": "kitchenowl",
@@ -718,9 +711,9 @@
{ {
"slug": "kubo", "slug": "kubo",
"repo": "ipfs/kubo", "repo": "ipfs/kubo",
"version": "v0.40.1", "version": "v0.39.0",
"pinned": false, "pinned": false,
"date": "2026-02-27T17:58:22Z" "date": "2025-11-27T03:47:38Z"
}, },
{ {
"slug": "kutt", "slug": "kutt",
@@ -753,9 +746,9 @@
{ {
"slug": "libretranslate", "slug": "libretranslate",
"repo": "LibreTranslate/LibreTranslate", "repo": "LibreTranslate/LibreTranslate",
"version": "v1.9.4", "version": "v1.9.3",
"pinned": false, "pinned": false,
"date": "2026-02-24T17:06:05Z" "date": "2026-02-21T19:08:33Z"
}, },
{ {
"slug": "lidarr", "slug": "lidarr",
@@ -795,9 +788,9 @@
{ {
"slug": "lubelogger", "slug": "lubelogger",
"repo": "hargata/lubelog", "repo": "hargata/lubelog",
"version": "v1.6.1", "version": "v1.6.0",
"pinned": false, "pinned": false,
"date": "2026-02-26T20:01:24Z" "date": "2026-02-10T20:16:32Z"
}, },
{ {
"slug": "mafl", "slug": "mafl",
@@ -816,9 +809,9 @@
{ {
"slug": "mail-archiver", "slug": "mail-archiver",
"repo": "s1t5/mail-archiver", "repo": "s1t5/mail-archiver",
"version": "2602.4", "version": "2602.3",
"pinned": false, "pinned": false,
"date": "2026-02-26T08:43:01Z" "date": "2026-02-22T20:24:18Z"
}, },
{ {
"slug": "managemydamnlife", "slug": "managemydamnlife",
@@ -830,9 +823,9 @@
{ {
"slug": "manyfold", "slug": "manyfold",
"repo": "manyfold3d/manyfold", "repo": "manyfold3d/manyfold",
"version": "v0.133.1", "version": "v0.132.1",
"pinned": false, "pinned": false,
"date": "2026-02-26T15:50:34Z" "date": "2026-02-09T22:02:28Z"
}, },
{ {
"slug": "mealie", "slug": "mealie",
@@ -851,9 +844,9 @@
{ {
"slug": "mediamtx", "slug": "mediamtx",
"repo": "bluenviron/mediamtx", "repo": "bluenviron/mediamtx",
"version": "v1.16.3", "version": "v1.16.2",
"pinned": false, "pinned": false,
"date": "2026-03-01T15:49:12Z" "date": "2026-02-22T17:31:41Z"
}, },
{ {
"slug": "meilisearch", "slug": "meilisearch",
@@ -872,9 +865,9 @@
{ {
"slug": "metube", "slug": "metube",
"repo": "alexta69/metube", "repo": "alexta69/metube",
"version": "2026.03.02", "version": "2026.02.22",
"pinned": false, "pinned": false,
"date": "2026-03-02T19:19:10Z" "date": "2026-02-22T00:58:45Z"
}, },
{ {
"slug": "miniflux", "slug": "miniflux",
@@ -942,9 +935,9 @@
{ {
"slug": "nightscout", "slug": "nightscout",
"repo": "nightscout/cgm-remote-monitor", "repo": "nightscout/cgm-remote-monitor",
"version": "v15.0.5", "version": "15.0.3",
"pinned": false, "pinned": false,
"date": "2026-03-01T21:22:37Z" "date": "2025-05-08T22:12:34Z"
}, },
{ {
"slug": "nocodb", "slug": "nocodb",
@@ -956,9 +949,9 @@
{ {
"slug": "nodebb", "slug": "nodebb",
"repo": "NodeBB/NodeBB", "repo": "NodeBB/NodeBB",
"version": "v4.9.1", "version": "v4.8.1",
"pinned": false, "pinned": false,
"date": "2026-03-01T20:52:43Z" "date": "2026-01-28T14:19:11Z"
}, },
{ {
"slug": "nodecast-tv", "slug": "nodecast-tv",
@@ -970,9 +963,9 @@
{ {
"slug": "oauth2-proxy", "slug": "oauth2-proxy",
"repo": "oauth2-proxy/oauth2-proxy", "repo": "oauth2-proxy/oauth2-proxy",
"version": "v7.14.3", "version": "v7.14.2",
"pinned": false, "pinned": false,
"date": "2026-02-26T14:10:21Z" "date": "2026-01-18T00:26:09Z"
}, },
{ {
"slug": "ombi", "slug": "ombi",
@@ -984,9 +977,9 @@
{ {
"slug": "open-archiver", "slug": "open-archiver",
"repo": "LogicLabs-OU/OpenArchiver", "repo": "LogicLabs-OU/OpenArchiver",
"version": "v0.4.2", "version": "v0.4.1",
"pinned": false, "pinned": false,
"date": "2026-02-24T20:47:40Z" "date": "2026-01-17T12:24:31Z"
}, },
{ {
"slug": "opencloud", "slug": "opencloud",
@@ -1002,13 +995,6 @@
"pinned": false, "pinned": false,
"date": "2026-02-03T09:00:43Z" "date": "2026-02-03T09:00:43Z"
}, },
{
"slug": "openproject",
"repo": "jemalloc/jemalloc",
"version": "5.3.0",
"pinned": false,
"date": "2022-05-06T19:14:21Z"
},
{ {
"slug": "ots", "slug": "ots",
"repo": "Luzifer/ots", "repo": "Luzifer/ots",
@@ -1037,12 +1023,19 @@
"pinned": false, "pinned": false,
"date": "2025-02-24T19:47:06Z" "date": "2025-02-24T19:47:06Z"
}, },
{
"slug": "palmr",
"repo": "kyantech/Palmr",
"version": "v3.3.2-beta",
"pinned": false,
"date": "2025-12-10T05:42:43Z"
},
{ {
"slug": "pangolin", "slug": "pangolin",
"repo": "fosrl/pangolin", "repo": "fosrl/pangolin",
"version": "1.16.2", "version": "1.15.4",
"pinned": false, "pinned": false,
"date": "2026-02-28T20:35:52Z" "date": "2026-02-13T23:01:29Z"
}, },
{ {
"slug": "paperless-ai", "slug": "paperless-ai",
@@ -1054,16 +1047,16 @@
{ {
"slug": "paperless-gpt", "slug": "paperless-gpt",
"repo": "icereed/paperless-gpt", "repo": "icereed/paperless-gpt",
"version": "v0.25.1", "version": "v0.25.0",
"pinned": false, "pinned": false,
"date": "2026-02-26T14:50:11Z" "date": "2026-02-16T08:31:48Z"
}, },
{ {
"slug": "paperless-ngx", "slug": "paperless-ngx",
"repo": "paperless-ngx/paperless-ngx", "repo": "paperless-ngx/paperless-ngx",
"version": "v2.20.9", "version": "v2.20.8",
"pinned": false, "pinned": false,
"date": "2026-02-28T10:17:35Z" "date": "2026-02-22T01:40:54Z"
}, },
{ {
"slug": "patchmon", "slug": "patchmon",
@@ -1124,9 +1117,9 @@
{ {
"slug": "planka", "slug": "planka",
"repo": "plankanban/planka", "repo": "plankanban/planka",
"version": "v2.0.3", "version": "v2.0.2",
"pinned": false, "pinned": false,
"date": "2026-03-01T16:03:23Z" "date": "2026-02-23T17:47:15Z"
}, },
{ {
"slug": "plant-it", "slug": "plant-it",
@@ -1149,13 +1142,6 @@
"pinned": false, "pinned": false,
"date": "2026-02-23T19:50:48Z" "date": "2026-02-23T19:50:48Z"
}, },
{
"slug": "powerdns",
"repo": "poweradmin/poweradmin",
"version": "v4.0.7",
"pinned": false,
"date": "2026-02-15T20:09:48Z"
},
{ {
"slug": "privatebin", "slug": "privatebin",
"repo": "PrivateBin/PrivateBin", "repo": "PrivateBin/PrivateBin",
@@ -1163,13 +1149,6 @@
"pinned": false, "pinned": false,
"date": "2025-11-12T07:10:14Z" "date": "2025-11-12T07:10:14Z"
}, },
{
"slug": "profilarr",
"repo": "Dictionarry-Hub/profilarr",
"version": "v1.1.4",
"pinned": false,
"date": "2026-01-29T14:57:25Z"
},
{ {
"slug": "projectsend", "slug": "projectsend",
"repo": "projectsend/projectsend", "repo": "projectsend/projectsend",
@@ -1180,9 +1159,9 @@
{ {
"slug": "prometheus", "slug": "prometheus",
"repo": "prometheus/prometheus", "repo": "prometheus/prometheus",
"version": "v3.10.0", "version": "v3.9.1",
"pinned": false, "pinned": false,
"date": "2026-02-26T01:19:51Z" "date": "2026-01-07T17:05:53Z"
}, },
{ {
"slug": "prometheus-alertmanager", "slug": "prometheus-alertmanager",
@@ -1229,9 +1208,9 @@
{ {
"slug": "pulse", "slug": "pulse",
"repo": "rcourtman/Pulse", "repo": "rcourtman/Pulse",
"version": "v5.1.17", "version": "v5.1.13",
"pinned": false, "pinned": false,
"date": "2026-03-02T20:15:31Z" "date": "2026-02-22T12:40:41Z"
}, },
{ {
"slug": "pve-scripts-local", "slug": "pve-scripts-local",
@@ -1278,9 +1257,9 @@
{ {
"slug": "radicale", "slug": "radicale",
"repo": "Kozea/Radicale", "repo": "Kozea/Radicale",
"version": "v3.6.1", "version": "v3.6.0",
"pinned": false, "pinned": false,
"date": "2026-02-24T06:36:23Z" "date": "2026-01-10T06:56:46Z"
}, },
{ {
"slug": "rclone", "slug": "rclone",
@@ -1292,9 +1271,9 @@
{ {
"slug": "rdtclient", "slug": "rdtclient",
"repo": "rogerfar/rdt-client", "repo": "rogerfar/rdt-client",
"version": "v2.0.125", "version": "v2.0.124",
"pinned": false, "pinned": false,
"date": "2026-03-01T18:29:10Z" "date": "2026-02-24T03:18:03Z"
}, },
{ {
"slug": "reactive-resume", "slug": "reactive-resume",
@@ -1306,9 +1285,9 @@
{ {
"slug": "recyclarr", "slug": "recyclarr",
"repo": "recyclarr/recyclarr", "repo": "recyclarr/recyclarr",
"version": "v8.3.2", "version": "v8.2.1",
"pinned": false, "pinned": false,
"date": "2026-02-25T22:39:51Z" "date": "2026-02-22T19:19:49Z"
}, },
{ {
"slug": "reitti", "slug": "reitti",
@@ -1355,9 +1334,9 @@
{ {
"slug": "scanopy", "slug": "scanopy",
"repo": "scanopy/scanopy", "repo": "scanopy/scanopy",
"version": "v0.14.11", "version": "v0.14.7",
"pinned": false, "pinned": false,
"date": "2026-03-02T08:48:42Z" "date": "2026-02-23T01:36:44Z"
}, },
{ {
"slug": "scraparr", "slug": "scraparr",
@@ -1383,16 +1362,16 @@
{ {
"slug": "seerr", "slug": "seerr",
"repo": "seerr-team/seerr", "repo": "seerr-team/seerr",
"version": "v3.1.0", "version": "v3.0.1",
"pinned": false, "pinned": false,
"date": "2026-02-27T17:25:29Z" "date": "2026-02-14T19:30:24Z"
}, },
{ {
"slug": "semaphore", "slug": "semaphore",
"repo": "semaphoreui/semaphore", "repo": "semaphoreui/semaphore",
"version": "v2.17.15", "version": "v2.17.12",
"pinned": false, "pinned": false,
"date": "2026-02-28T09:04:40Z" "date": "2026-02-20T09:16:50Z"
}, },
{ {
"slug": "shelfmark", "slug": "shelfmark",
@@ -1404,9 +1383,9 @@
{ {
"slug": "signoz", "slug": "signoz",
"repo": "SigNoz/signoz-otel-collector", "repo": "SigNoz/signoz-otel-collector",
"version": "v0.144.2", "version": "v0.142.1",
"pinned": false, "pinned": false,
"date": "2026-02-26T05:57:26Z" "date": "2026-02-21T18:04:07Z"
}, },
{ {
"slug": "silverbullet", "slug": "silverbullet",
@@ -1418,9 +1397,9 @@
{ {
"slug": "slskd", "slug": "slskd",
"repo": "slskd/slskd", "repo": "slskd/slskd",
"version": "0.24.5", "version": "0.24.4",
"pinned": false, "pinned": false,
"date": "2026-03-01T04:00:42Z" "date": "2026-02-16T16:50:17Z"
}, },
{ {
"slug": "snipeit", "slug": "snipeit",
@@ -1432,9 +1411,9 @@
{ {
"slug": "snowshare", "slug": "snowshare",
"repo": "TuroYT/snowshare", "repo": "TuroYT/snowshare",
"version": "v1.3.8", "version": "v1.3.7",
"pinned": false, "pinned": false,
"date": "2026-03-02T07:43:42Z" "date": "2026-02-23T15:51:39Z"
}, },
{ {
"slug": "sonarr", "slug": "sonarr",
@@ -1495,9 +1474,9 @@
{ {
"slug": "sure", "slug": "sure",
"repo": "we-promise/sure", "repo": "we-promise/sure",
"version": "v0.6.8", "version": "chart-v0.6.8-alpha.13",
"pinned": false, "pinned": false,
"date": "2026-02-28T12:55:36Z" "date": "2026-02-20T11:15:15Z"
}, },
{ {
"slug": "tandoor", "slug": "tandoor",
@@ -1562,26 +1541,19 @@
"pinned": false, "pinned": false,
"date": "2026-02-13T16:30:09Z" "date": "2026-02-13T16:30:09Z"
}, },
{
"slug": "tinyauth",
"repo": "steveiliop56/tinyauth",
"version": "v5.0.0",
"pinned": false,
"date": "2026-03-02T18:43:57Z"
},
{ {
"slug": "traccar", "slug": "traccar",
"repo": "traccar/traccar", "repo": "traccar/traccar",
"version": "v6.12.2", "version": "v6.12.1",
"pinned": false, "pinned": false,
"date": "2026-02-27T15:08:36Z" "date": "2026-02-22T18:47:37Z"
}, },
{ {
"slug": "tracearr", "slug": "tracearr",
"repo": "connorgallopo/Tracearr", "repo": "connorgallopo/Tracearr",
"version": "v1.4.19", "version": "v1.4.18",
"pinned": false, "pinned": false,
"date": "2026-02-28T21:25:47Z" "date": "2026-02-15T19:55:40Z"
}, },
{ {
"slug": "tracktor", "slug": "tracktor",
@@ -1600,9 +1572,9 @@
{ {
"slug": "trilium", "slug": "trilium",
"repo": "TriliumNext/Trilium", "repo": "TriliumNext/Trilium",
"version": "v0.102.0", "version": "v0.101.3",
"pinned": false, "pinned": false,
"date": "2026-03-01T20:37:40Z" "date": "2026-01-08T18:05:22Z"
}, },
{ {
"slug": "trip", "slug": "trip",
@@ -1621,9 +1593,9 @@
{ {
"slug": "tunarr", "slug": "tunarr",
"repo": "chrisbenincasa/tunarr", "repo": "chrisbenincasa/tunarr",
"version": "v1.1.18", "version": "v1.1.16",
"pinned": false, "pinned": false,
"date": "2026-02-26T22:09:44Z" "date": "2026-02-23T21:24:47Z"
}, },
{ {
"slug": "uhf", "slug": "uhf",
@@ -1649,9 +1621,9 @@
{ {
"slug": "upgopher", "slug": "upgopher",
"repo": "wanetty/upgopher", "repo": "wanetty/upgopher",
"version": "v1.14.0", "version": "v1.13.0",
"pinned": false, "pinned": false,
"date": "2026-02-24T22:43:34Z" "date": "2026-01-16T20:26:34Z"
}, },
{ {
"slug": "upsnap", "slug": "upsnap",
@@ -1677,16 +1649,16 @@
{ {
"slug": "victoriametrics", "slug": "victoriametrics",
"repo": "VictoriaMetrics/VictoriaMetrics", "repo": "VictoriaMetrics/VictoriaMetrics",
"version": "v1.137.0", "version": "v1.136.0",
"pinned": false, "pinned": false,
"date": "2026-03-02T10:09:29Z" "date": "2026-02-16T13:17:50Z"
}, },
{ {
"slug": "vikunja", "slug": "vikunja",
"repo": "go-vikunja/vikunja", "repo": "go-vikunja/vikunja",
"version": "v2.1.0", "version": "v1.1.0",
"pinned": false, "pinned": false,
"date": "2026-02-27T14:26:53Z" "date": "2026-02-09T10:34:29Z"
}, },
{ {
"slug": "wallabag", "slug": "wallabag",
@@ -1705,9 +1677,9 @@
{ {
"slug": "wanderer", "slug": "wanderer",
"repo": "meilisearch/meilisearch", "repo": "meilisearch/meilisearch",
"version": "v1.37.0", "version": "v1.36.0",
"pinned": false, "pinned": false,
"date": "2026-03-02T09:16:36Z" "date": ""
}, },
{ {
"slug": "warracker", "slug": "warracker",
@@ -1740,9 +1712,9 @@
{ {
"slug": "wealthfolio", "slug": "wealthfolio",
"repo": "afadil/wealthfolio", "repo": "afadil/wealthfolio",
"version": "v3.0.2", "version": "v2.1.0",
"pinned": false, "pinned": false,
"date": "2026-03-03T05:01:49Z" "date": "2025-12-01T21:57:36Z"
}, },
{ {
"slug": "web-check", "slug": "web-check",
@@ -1775,9 +1747,9 @@
{ {
"slug": "wizarr", "slug": "wizarr",
"repo": "wizarrrr/wizarr", "repo": "wizarrrr/wizarr",
"version": "v2026.2.1", "version": "v2026.2.0",
"pinned": false, "pinned": false,
"date": "2026-02-25T01:07:56Z" "date": "2026-02-23T19:25:28Z"
}, },
{ {
"slug": "writefreely", "slug": "writefreely",
@@ -1796,23 +1768,16 @@
{ {
"slug": "yubal", "slug": "yubal",
"repo": "guillevc/yubal", "repo": "guillevc/yubal",
"version": "v0.6.2", "version": "v0.6.1",
"pinned": false, "pinned": false,
"date": "2026-02-24T15:15:46Z" "date": "2026-02-18T23:24:16Z"
},
{
"slug": "zerobyte",
"repo": "restic/restic",
"version": "v0.18.1",
"pinned": false,
"date": "2025-09-21T18:24:38Z"
}, },
{ {
"slug": "zigbee2mqtt", "slug": "zigbee2mqtt",
"repo": "Koenkk/zigbee2mqtt", "repo": "Koenkk/zigbee2mqtt",
"version": "2.9.1", "version": "2.8.0",
"pinned": false, "pinned": false,
"date": "2026-03-02T11:16:46Z" "date": "2026-02-01T19:27:25Z"
}, },
{ {
"slug": "zipline", "slug": "zipline",
@@ -1824,16 +1789,16 @@
{ {
"slug": "zitadel", "slug": "zitadel",
"repo": "zitadel/zitadel", "repo": "zitadel/zitadel",
"version": "v4.12.0", "version": "v4.11.0",
"pinned": false, "pinned": false,
"date": "2026-03-02T08:16:10Z" "date": "2026-02-16T09:48:38Z"
}, },
{ {
"slug": "zoraxy", "slug": "zoraxy",
"repo": "tobychui/zoraxy", "repo": "tobychui/zoraxy",
"version": "v3.3.2-rc2", "version": "v3.3.2-rc1",
"pinned": false, "pinned": false,
"date": "2026-02-27T03:31:25Z" "date": "2026-02-15T02:16:17Z"
}, },
{ {
"slug": "zwave-js-ui", "slug": "zwave-js-ui",

View File

@@ -51,10 +51,6 @@
{ {
"text": "Logs: `/var/log/immich`", "text": "Logs: `/var/log/immich`",
"type": "info" "type": "info"
},
{
"text": "During first install, 5 custom libraries need to be compiled from source. Depending on your CPU, this can take anywhere between 15 minutes and 2 hours. Please be patient. Touch grass or something.",
"type": "warning"
} }
] ]
} }

View File

@@ -1,48 +0,0 @@
{
"name": "Kima-Hub",
"slug": "kima-hub",
"categories": [
13
],
"date_created": "2026-02-26",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3030,
"documentation": "https://github.com/Chevron7Locked/kima-hub#readme",
"website": "https://github.com/Chevron7Locked/kima-hub",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/kima-hub.webp",
"config_path": "/opt/kima-hub/backend/.env",
"description": "Self-hosted, on-demand audio streaming platform with AI-powered vibe matching, mood detection, smart playlists, and Lidarr/Audiobookshelf integration.",
"install_methods": [
{
"type": "default",
"script": "ct/kima-hub.sh",
"resources": {
"cpu": 4,
"ram": 8192,
"hdd": 20,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "First user to register becomes the administrator.",
"type": "info"
},
{
"text": "Mount your music library to /music in the container.",
"type": "warning"
},
{
"text": "Audio analysis (mood/vibe detection) requires significant RAM (2-4GB per worker).",
"type": "info"
}
]
}

View File

@@ -5,7 +5,7 @@
3 3
], ],
"date_created": "2025-01-01", "date_created": "2025-01-01",
"type": "addon", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": 9120, "interface_port": 9120,
@@ -17,13 +17,24 @@
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "tools/addon/komodo.sh", "script": "ct/komodo.sh",
"resources": { "resources": {
"cpu": null, "cpu": 2,
"ram": null, "ram": 2048,
"hdd": null, "hdd": 10,
"os": null, "os": "debian",
"version": null "version": "13"
}
},
{
"type": "alpine",
"script": "ct/alpine-komodo.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 10,
"os": "alpine",
"version": "3.23"
} }
} }
], ],
@@ -33,19 +44,7 @@
}, },
"notes": [ "notes": [
{ {
"text": "This is an addon script intended to be used on top of an existing Docker container.", "text": "For admin username and password type `cat ~/komodo.creds` inside LXC.",
"type": "info"
},
{
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)",
"type": "info"
},
{
"text": "For admin username and password, run: cat ~/komodo.creds",
"type": "info"
},
{
"text": "To update, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)",
"type": "info" "type": "info"
} }
] ]

View File

@@ -23,7 +23,7 @@
"ram": 4096, "ram": 4096,
"hdd": 8, "hdd": 8,
"os": "Debian", "os": "Debian",
"version": "13" "version": "12"
} }
} }
], ],
@@ -31,10 +31,5 @@
"username": "admin", "username": "admin",
"password": "admin" "password": "admin"
}, },
"notes": [ "notes": []
{
"text": "If you want to update from v15.x to v17.x, please read `https://www.openproject.org/docs/installation-and-operations/operation/upgrading/#major-upgrades` before doing so.",
"type": "warning"
}
]
} }

View File

@@ -0,0 +1,45 @@
{
"name": "Palmr",
"slug": "palmr",
"categories": [
11
],
"date_created": "2025-08-08",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"disable": true,
"documentation": "https://palmr.kyantech.com.br/docs/3.1-beta",
"config_path": "/opt/palmr/apps/server/.env, /opt/palmr/apps/web/.env",
"website": "https://palmr.kyantech.com.br/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/palmr.webp",
"description": "Palmr is a fast and secure platform for sharing files, built with performance and privacy in mind.",
"install_methods": [
{
"type": "default",
"script": "ct/palmr.sh",
"resources": {
"cpu": 4,
"ram": 6144,
"hdd": 6,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "To use a bind mount for storage, create symlinks to your mount for both `uploads` and `temp-uploads` in `/opt/palmr_data`, and uncomment `CUSTOM_PATH` to add the path to your bind mount",
"type": "info"
},
{
"text": "To use Palmr with a reverse proxy, uncomment `SECURE_SITE` in `/opt/palmr/apps/server/.env`",
"type": "info"
}
]
}

View File

@@ -21,7 +21,7 @@
"resources": { "resources": {
"cpu": 2, "cpu": 2,
"ram": 4096, "ram": 4096,
"hdd": 10, "hdd": 5,
"os": "Debian", "os": "Debian",
"version": "13" "version": "13"
} }

View File

@@ -1,40 +0,0 @@
{
"name": "PowerDNS",
"slug": "powerdns",
"categories": [
5
],
"date_created": "2026-03-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://doc.powerdns.com/index.html",
"config_path": "/opt/poweradmin/config/settings.php",
"website": "https://www.powerdns.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/powerdns.webp",
"description": "The PowerDNS Authoritative Server is a versatile nameserver which supports a large number of backends. These backends can either be plain zone files or be more dynamic in nature. PowerDNS has the concepts of backends. A backend is a datastore that the server will consult that contains DNS records (and some metadata). The backends range from database backends (MySQL, PostgreSQL) and BIND zone files to co-processes and JSON APIs.",
"install_methods": [
{
"type": "default",
"script": "ct/powerdns.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "For administrator credentials type: `cat ~/poweradmin.creds` inside LXC.",
"type": "info"
}
]
}

View File

@@ -1,35 +0,0 @@
{
"name": "Profilarr",
"slug": "profilarr",
"categories": [
14
],
"date_created": "2026-03-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 6868,
"documentation": "https://github.com/Dictionarry-Hub/profilarr#readme",
"website": "https://github.com/Dictionarry-Hub/profilarr",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/profilarr.webp",
"config_path": "/config",
"description": "Profilarr is a configuration management platform for Radarr and Sonarr that simplifies importing, syncing, and managing quality profiles, custom formats, and release profiles.",
"install_methods": [
{
"type": "default",
"script": "ct/profilarr.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -5,25 +5,25 @@
2 2
], ],
"date_created": "2024-05-02", "date_created": "2024-05-02",
"type": "addon", "type": "ct",
"updateable": true, "updateable": true,
"privileged": false, "privileged": false,
"interface_port": 80, "interface_port": 80,
"documentation": "https://runtipi.io/docs/introduction", "documentation": "https://runtipi.io/docs/introduction",
"website": "https://runtipi.io/", "website": "https://runtipi.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/runtipi.webp", "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/runtipi.webp",
"config_path": "/opt/runtipi/state/settings.json", "config_path": "opt/runtipi/state/settings.json",
"description": "Runtipi lets you install all your favorite self-hosted apps without the hassle of configuring and managing each service. One-click installs and updates for more than 180 popular apps.", "description": "Runtipi lets you install all your favorite self-hosted apps without the hassle of configuring and managing each service. One-click installs and updates for more than 180 popular apps.",
"install_methods": [ "install_methods": [
{ {
"type": "default", "type": "default",
"script": "tools/addon/runtipi.sh", "script": "ct/runtipi.sh",
"resources": { "resources": {
"cpu": null, "cpu": 2,
"ram": null, "ram": 2048,
"hdd": null, "hdd": 8,
"os": null, "os": "debian",
"version": null "version": "13"
} }
} }
], ],
@@ -32,21 +32,9 @@
"password": null "password": null
}, },
"notes": [ "notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
{
"text": "Execute within an existing LXC console (Debian / Ubuntu only)",
"type": "info"
},
{ {
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.", "text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning" "type": "warning"
},
{
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh)",
"type": "info"
} }
] ]
} }

View File

@@ -1,48 +0,0 @@
{
"name": "Strapi",
"slug": "strapi",
"categories": [
12
],
"date_created": "2026-02-27",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 1337,
"documentation": "https://docs.strapi.io/",
"website": "https://strapi.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/strapi.webp",
"config_path": "/opt/strapi/.env",
"description": "Strapi is a leading open-source headless CMS that enables developers to build powerful APIs quickly. It features a flexible content structure with customizable content types, supporting both REST and GraphQL APIs. The intuitive admin panel allows non-technical users to manage content easily, while developers can extend functionality through plugins. Built on Node.js, Strapi offers role-based access control, media library management, and internationalization support out of the box.",
"install_methods": [
{
"type": "default",
"script": "ct/strapi.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 8,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "First-time setup requires creating an admin account at http://IP:1337/admin",
"type": "info"
},
{
"text": "Default installation uses SQLite. For production use, consider configuring PostgreSQL or MySQL.",
"type": "info"
},
{
"text": "Building the admin panel requires 4GB RAM. Container may take 10-15 minutes to fully initialize.",
"type": "warning"
}
]
}

View File

@@ -0,0 +1,42 @@
{
"name": "UniFi Network Server",
"slug": "unifi",
"categories": [
4
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8443,
"documentation": "https://help.ui.com/hc/en-us/articles/360012282453-Self-Hosting-a-UniFi-Network-Server",
"website": "https://www.ui.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/ubiquiti-unifi.webp",
"config_path": "",
"description": "UniFi Network Server is a software that helps manage and monitor UniFi networks (Wi-Fi, Ethernet, etc.) by providing an intuitive user interface and advanced features. It allows network administrators to configure, monitor, and upgrade network devices, as well as view network statistics, client devices, and historical events. The aim of the application is to make the management of UniFi networks easier and more efficient.",
"disable": true,
"disable_description": "This script is disabled because UniFi no longer delivers APT packages for Debian systems. The installation relies on APT repositories that are no longer maintained or available. For more details, see: https://github.com/community-scripts/ProxmoxVE/issues/11876",
"install_methods": [
{
"type": "default",
"script": "ct/unifi.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "For non-AVX CPUs, MongoDB 4.4 is installed. Please note this is a legacy solution that may present security risks and could become unsupported in future updates.",
"type": "warning"
}
]
}

View File

@@ -1,40 +0,0 @@
{
"name": "Zerobyte",
"slug": "zerobyte",
"categories": [
7
],
"date_created": "2026-02-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 4096,
"documentation": "https://github.com/nicotsx/zerobyte#readme",
"website": "https://github.com/nicotsx/zerobyte",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/zerobyte.webp",
"config_path": "/opt/zerobyte/.env",
"description": "Zerobyte is a backup automation tool built on top of Restic that provides a modern web interface to schedule, manage, and monitor encrypted backups across multiple storage backends including NFS, SMB, WebDAV, SFTP, S3, and local directories.",
"install_methods": [
{
"type": "default",
"script": "ct/zerobyte.sh",
"resources": {
"cpu": 2,
"ram": 6144,
"hdd": 10,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "For remote mount support (NFS, SMB, WebDAV, SFTP), enable FUSE device passthrough on the LXC container. (FUSE is pre-configured)",
"type": "info"
}
]
}

View File

@@ -2,68 +2,42 @@
import type { z } from "zod"; import type { z } from "zod";
import { githubGist, nord } from "react-syntax-highlighter/dist/esm/styles/hljs";
import { CalendarIcon, Check, Clipboard, Download } from "lucide-react"; import { CalendarIcon, Check, Clipboard, Download } from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import SyntaxHighlighter from "react-syntax-highlighter";
import { useTheme } from "next-themes";
import { format } from "date-fns"; import { format } from "date-fns";
import { toast } from "sonner"; import { toast } from "sonner";
import Image from "next/image";
import type { Category } from "@/lib/types"; import type { Category } from "@/lib/types";
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Calendar } from "@/components/ui/calendar"; import { Calendar } from "@/components/ui/calendar";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { basePath } from "@/config/site-config";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { fetchCategories } from "@/lib/data"; import { fetchCategories } from "@/lib/data";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import type { Script } from "./_schemas/schemas"; import type { Script } from "./_schemas/schemas";
import { ScriptItem } from "../scripts/_components/script-item";
import InstallMethod from "./_components/install-method"; import InstallMethod from "./_components/install-method";
import { ScriptSchema } from "./_schemas/schemas"; import { ScriptSchema } from "./_schemas/schemas";
import Categories from "./_components/categories"; import Categories from "./_components/categories";
import Note from "./_components/note"; import Note from "./_components/note";
function search(scripts: Script[], query: string): Script[] { import { githubGist, nord } from "react-syntax-highlighter/dist/esm/styles/hljs";
const queryLower = query.toLowerCase().trim(); import SyntaxHighlighter from "react-syntax-highlighter";
const searchWords = queryLower.split(/\s+/).filter(Boolean); import { ScriptItem } from "../scripts/_components/script-item";
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
return scripts import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
.map((script) => { import { search } from "@/components/command-menu";
const nameLower = script.name.toLowerCase(); import { basePath } from "@/config/site-config";
const descriptionLower = (script.description || "").toLowerCase(); import Image from "next/image";
import { useTheme } from "next-themes";
let score = 0;
for (const word of searchWords) {
if (nameLower.includes(word)) {
score += 10;
}
if (descriptionLower.includes(word)) {
score += 5;
}
}
return { script, score };
})
.filter(({ score }) => score > 0)
.sort((a, b) => b.score - a.score)
.slice(0, 20)
.map(({ script }) => script);
}
const initialScript: Script = { const initialScript: Script = {
name: "", name: "",
@@ -103,32 +77,32 @@ export default function JSONGenerator() {
const selectedCategoryObj = useMemo( const selectedCategoryObj = useMemo(
() => categories.find(cat => cat.id.toString() === selectedCategory), () => categories.find(cat => cat.id.toString() === selectedCategory),
[categories, selectedCategory], [categories, selectedCategory]
); );
const allScripts = useMemo( const allScripts = useMemo(
() => categories.flatMap(cat => cat.scripts || []), () => categories.flatMap(cat => cat.scripts || []),
[categories], [categories]
); );
const scripts = useMemo(() => { const scripts = useMemo(() => {
const query = searchQuery.trim(); const query = searchQuery.trim()
if (query) { if (query) {
return search(allScripts, query); return search(allScripts, query)
} }
if (selectedCategoryObj) { if (selectedCategoryObj) {
return selectedCategoryObj.scripts || []; return selectedCategoryObj.scripts || []
} }
return []; return []
}, [allScripts, selectedCategoryObj, searchQuery]); }, [allScripts, selectedCategoryObj, searchQuery]);
useEffect(() => { useEffect(() => {
fetchCategories() fetchCategories()
.then(setCategories) .then(setCategories)
.catch(error => console.error("Error fetching categories:", error)); .catch((error) => console.error("Error fetching categories:", error));
}, []); }, []);
useEffect(() => { useEffect(() => {
@@ -148,14 +122,11 @@ export default function JSONGenerator() {
if (updated.type === "pve") { if (updated.type === "pve") {
scriptPath = `tools/pve/${updated.slug}.sh`; scriptPath = `tools/pve/${updated.slug}.sh`;
} } else if (updated.type === "addon") {
else if (updated.type === "addon") {
scriptPath = `tools/addon/${updated.slug}.sh`; scriptPath = `tools/addon/${updated.slug}.sh`;
} } else if (method.type === "alpine") {
else if (method.type === "alpine") {
scriptPath = `${updated.type}/alpine-${updated.slug}.sh`; scriptPath = `${updated.type}/alpine-${updated.slug}.sh`;
} } else {
else {
scriptPath = `${updated.type}/${updated.slug}.sh`; scriptPath = `${updated.type}/${updated.slug}.sh`;
} }
@@ -174,13 +145,11 @@ export default function JSONGenerator() {
}, []); }, []);
const handleCopy = useCallback(() => { const handleCopy = useCallback(() => {
if (!isValid) if (!isValid) toast.warning("JSON schema is invalid. Copying anyway.");
toast.warning("JSON schema is invalid. Copying anyway.");
navigator.clipboard.writeText(JSON.stringify(script, null, 2)); navigator.clipboard.writeText(JSON.stringify(script, null, 2));
setIsCopied(true); setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000); setTimeout(() => setIsCopied(false), 2000);
if (isValid) if (isValid) toast.success("Copied metadata to clipboard");
toast.success("Copied metadata to clipboard");
}, [script]); }, [script]);
const importScript = (script: Script) => { const importScript = (script: Script) => {
@@ -197,11 +166,11 @@ export default function JSONGenerator() {
setIsValid(true); setIsValid(true);
setZodErrors(null); setZodErrors(null);
toast.success("Imported JSON successfully"); toast.success("Imported JSON successfully");
} } catch (error) {
catch (error) {
toast.error("Failed to read or parse the JSON file."); toast.error("Failed to read or parse the JSON file.");
} }
};
}
const handleFileImport = useCallback(() => { const handleFileImport = useCallback(() => {
const input = document.createElement("input"); const input = document.createElement("input");
@@ -211,8 +180,7 @@ export default function JSONGenerator() {
input.onchange = (e: Event) => { input.onchange = (e: Event) => {
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement;
const file = target.files?.[0]; const file = target.files?.[0];
if (!file) if (!file) return;
return;
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (event) => { reader.onload = (event) => {
@@ -221,8 +189,7 @@ export default function JSONGenerator() {
const parsed = JSON.parse(content); const parsed = JSON.parse(content);
importScript(parsed); importScript(parsed);
toast.success("Imported JSON successfully"); toast.success("Imported JSON successfully");
} } catch (error) {
catch (error) {
toast.error("Failed to read the JSON file."); toast.error("Failed to read the JSON file.");
} }
}; };
@@ -276,10 +243,7 @@ export default function JSONGenerator() {
<div className="mt-2 space-y-1"> <div className="mt-2 space-y-1">
{zodErrors.issues.map((error, index) => ( {zodErrors.issues.map((error, index) => (
<AlertDescription key={index} className="p-1 text-red-500"> <AlertDescription key={index} className="p-1 text-red-500">
{error.path.join(".")} {error.path.join(".")} -{error.message}
{" "}
-
{error.message}
</AlertDescription> </AlertDescription>
))} ))}
</div> </div>
@@ -306,7 +270,7 @@ export default function JSONGenerator() {
onOpenChange={setIsImportDialogOpen} onOpenChange={setIsImportDialogOpen}
> >
<DialogTrigger asChild> <DialogTrigger asChild>
<DropdownMenuItem onSelect={e => e.preventDefault()}> <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
Import existing script Import existing script
</DropdownMenuItem> </DropdownMenuItem>
</DialogTrigger> </DialogTrigger>
@@ -328,7 +292,7 @@ export default function JSONGenerator() {
<SelectValue placeholder="Category" /> <SelectValue placeholder="Category" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{categories.map(category => ( {categories.map((category) => (
<SelectItem key={category.id} value={category.id.toString()}> <SelectItem key={category.id} value={category.id.toString()}>
{category.name} {category.name}
</SelectItem> </SelectItem>
@@ -338,44 +302,40 @@ export default function JSONGenerator() {
<Input <Input
placeholder="Search for a script..." placeholder="Search for a script..."
value={searchQuery} value={searchQuery}
onChange={e => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
/> />
{!selectedCategory && !searchQuery {!selectedCategory && !searchQuery ? (
? ( <p className="text-muted-foreground text-sm text-center">
<p className="text-muted-foreground text-sm text-center"> Select a category or search for a script
Select a category or search for a script </p>
</p> ) : scripts.length === 0 ? (
) <p className="text-muted-foreground text-sm text-center">
: scripts.length === 0 No scripts found
? ( </p>
<p className="text-muted-foreground text-sm text-center"> ) : (
No scripts found <div className="grid grid-cols-3 auto-rows-min h-64 overflow-y-auto gap-4">
</p> {scripts.map(script => (
) <div
: ( key={script.slug}
<div className="grid grid-cols-3 auto-rows-min h-64 overflow-y-auto gap-4"> className="p-2 border rounded cursor-pointer hover:bg-accent hover:text-accent-foreground"
{scripts.map(script => ( onClick={() => {
<div importScript(script);
key={script.slug} setIsImportDialogOpen(false);
className="p-2 border rounded cursor-pointer hover:bg-accent hover:text-accent-foreground" }}
onClick={() => { >
importScript(script); <Image
setIsImportDialogOpen(false); src={script.logo || `/${basePath}/logo.png`}
}} alt={script.name}
> className="w-full h-12 object-contain mb-2"
<Image width={16}
src={script.logo || `/${basePath}/logo.png`} height={16}
alt={script.name} unoptimized
className="w-full h-12 object-contain mb-2" />
width={16} <p className="text-sm text-center">{script.name}</p>
height={16} </div>
unoptimized ))}
/> </div>
<p className="text-sm text-center">{script.name}</p> )}
</div>
))}
</div>
)}
</div> </div>
</div> </div>
</DialogContent> </DialogContent>
@@ -388,19 +348,15 @@ export default function JSONGenerator() {
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<Label> <Label>
Name Name <span className="text-red-500">*</span>
{" "}
<span className="text-red-500">*</span>
</Label> </Label>
<Input placeholder="Example" value={script.name} onChange={e => updateScript("name", e.target.value)} /> <Input placeholder="Example" value={script.name} onChange={(e) => updateScript("name", e.target.value)} />
</div> </div>
<div> <div>
<Label> <Label>
Slug Slug <span className="text-red-500">*</span>
{" "}
<span className="text-red-500">*</span>
</Label> </Label>
<Input placeholder="example" value={script.slug} onChange={e => updateScript("slug", e.target.value)} /> <Input placeholder="example" value={script.slug} onChange={(e) => updateScript("slug", e.target.value)} />
</div> </div>
</div> </div>
<div> <div>
@@ -410,7 +366,7 @@ export default function JSONGenerator() {
<Input <Input
placeholder="Full logo URL" placeholder="Full logo URL"
value={script.logo || ""} value={script.logo || ""}
onChange={e => updateScript("logo", e.target.value || null)} onChange={(e) => updateScript("logo", e.target.value || null)}
/> />
</div> </div>
<div> <div>
@@ -418,28 +374,24 @@ export default function JSONGenerator() {
<Input <Input
placeholder="Path to config file" placeholder="Path to config file"
value={script.config_path || ""} value={script.config_path || ""}
onChange={e => updateScript("config_path", e.target.value || "")} onChange={(e) => updateScript("config_path", e.target.value || "")}
/> />
</div> </div>
<div> <div>
<Label> <Label>
Description Description <span className="text-red-500">*</span>
{" "}
<span className="text-red-500">*</span>
</Label> </Label>
<Textarea <Textarea
placeholder="Example" placeholder="Example"
value={script.description} value={script.description}
onChange={e => updateScript("description", e.target.value)} onChange={(e) => updateScript("description", e.target.value)}
/> />
</div> </div>
<Categories script={script} setScript={setScript} categories={categories} /> <Categories script={script} setScript={setScript} categories={categories} />
<div className="flex gap-2"> <div className="flex gap-2">
<div className="flex flex-col gap-2 w-full"> <div className="flex flex-col gap-2 w-full">
<Label> <Label>
Date Created Date Created <span className="text-red-500">*</span>
{" "}
<span className="text-red-500">*</span>
</Label> </Label>
<Popover> <Popover>
<PopoverTrigger asChild className="flex-1"> <PopoverTrigger asChild className="flex-1">
@@ -463,7 +415,7 @@ export default function JSONGenerator() {
</div> </div>
<div className="flex flex-col gap-2 w-full"> <div className="flex flex-col gap-2 w-full">
<Label>Type</Label> <Label>Type</Label>
<Select value={script.type} onValueChange={value => updateScript("type", value)}> <Select value={script.type} onValueChange={(value) => updateScript("type", value)}>
<SelectTrigger className="flex-1"> <SelectTrigger className="flex-1">
<SelectValue placeholder="Type" /> <SelectValue placeholder="Type" />
</SelectTrigger> </SelectTrigger>
@@ -478,17 +430,17 @@ export default function JSONGenerator() {
</div> </div>
<div className="w-full flex gap-5"> <div className="w-full flex gap-5">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Switch checked={script.updateable} onCheckedChange={checked => updateScript("updateable", checked)} /> <Switch checked={script.updateable} onCheckedChange={(checked) => updateScript("updateable", checked)} />
<label>Updateable</label> <label>Updateable</label>
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Switch checked={script.privileged} onCheckedChange={checked => updateScript("privileged", checked)} /> <Switch checked={script.privileged} onCheckedChange={(checked) => updateScript("privileged", checked)} />
<label>Privileged</label> <label>Privileged</label>
</div> </div>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<Switch <Switch
checked={script.disable || false} checked={script.disable || false}
onCheckedChange={checked => updateScript("disable", checked)} onCheckedChange={(checked) => updateScript("disable", checked)}
/> />
<label>Disabled</label> <label>Disabled</label>
</div> </div>
@@ -496,14 +448,12 @@ export default function JSONGenerator() {
{script.disable && ( {script.disable && (
<div> <div>
<Label> <Label>
Disable Description Disable Description <span className="text-red-500">*</span>
{" "}
<span className="text-red-500">*</span>
</Label> </Label>
<Textarea <Textarea
placeholder="Explain why this script is disabled..." placeholder="Explain why this script is disabled..."
value={script.disable_description || ""} value={script.disable_description || ""}
onChange={e => updateScript("disable_description", e.target.value)} onChange={(e) => updateScript("disable_description", e.target.value)}
/> />
</div> </div>
)} )}
@@ -511,18 +461,18 @@ export default function JSONGenerator() {
placeholder="Interface Port" placeholder="Interface Port"
type="number" type="number"
value={script.interface_port || ""} value={script.interface_port || ""}
onChange={e => updateScript("interface_port", e.target.value ? Number(e.target.value) : null)} onChange={(e) => updateScript("interface_port", e.target.value ? Number(e.target.value) : null)}
/> />
<div className="flex gap-2"> <div className="flex gap-2">
<Input <Input
placeholder="Website URL" placeholder="Website URL"
value={script.website || ""} value={script.website || ""}
onChange={e => updateScript("website", e.target.value || null)} onChange={(e) => updateScript("website", e.target.value || null)}
/> />
<Input <Input
placeholder="Documentation URL" placeholder="Documentation URL"
value={script.documentation || ""} value={script.documentation || ""}
onChange={e => updateScript("documentation", e.target.value || null)} onChange={(e) => updateScript("documentation", e.target.value || null)}
/> />
</div> </div>
<InstallMethod script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} /> <InstallMethod script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
@@ -530,20 +480,22 @@ export default function JSONGenerator() {
<Input <Input
placeholder="Username" placeholder="Username"
value={script.default_credentials.username || ""} value={script.default_credentials.username || ""}
onChange={e => onChange={(e) =>
updateScript("default_credentials", { updateScript("default_credentials", {
...script.default_credentials, ...script.default_credentials,
username: e.target.value || null, username: e.target.value || null,
})} })
}
/> />
<Input <Input
placeholder="Password" placeholder="Password"
value={script.default_credentials.password || ""} value={script.default_credentials.password || ""}
onChange={e => onChange={(e) =>
updateScript("default_credentials", { updateScript("default_credentials", {
...script.default_credentials, ...script.default_credentials,
password: e.target.value || null, password: e.target.value || null,
})} })
}
/> />
<Note script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} /> <Note script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
</form> </form>
@@ -552,7 +504,7 @@ export default function JSONGenerator() {
<Tabs <Tabs
defaultValue="json" defaultValue="json"
className="w-full" className="w-full"
onValueChange={value => setCurrentTab(value as "json" | "preview")} onValueChange={(value) => setCurrentTab(value as "json" | "preview")}
value={currentTab} value={currentTab}
> >
<TabsList className="grid w-full grid-cols-2"> <TabsList className="grid w-full grid-cols-2">

View File

@@ -19,9 +19,8 @@ export function getDisplayValueFromType(type: string) {
case "vm": case "vm":
return "VM"; return "VM";
case "pve": case "pve":
return "PVE";
case "addon": case "addon":
return "ADDON"; return "";
default: default:
return ""; return "";
} }
@@ -37,9 +36,10 @@ export function LatestScripts({
onPageChange: (page: number) => void; onPageChange: (page: number) => void;
}) { }) {
const latestScripts = useMemo(() => { const latestScripts = useMemo(() => {
if (!items) return []; if (!items)
return [];
const scripts = items.flatMap((category) => category.scripts || []); const scripts = items.flatMap(category => category.scripts || []);
// Filter out duplicates by slug // Filter out duplicates by slug
const uniqueScriptsMap = new Map<string, Script>(); const uniqueScriptsMap = new Map<string, Script>();
@@ -97,7 +97,7 @@ export function LatestScripts({
</div> </div>
)} )}
<div className="min-w flex w-full flex-row flex-wrap gap-4"> <div className="min-w flex w-full flex-row flex-wrap gap-4">
{latestScripts.slice(startIndex, endIndex).map((script) => ( {latestScripts.slice(startIndex, endIndex).map(script => (
<Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30"> <Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-3"> <CardTitle className="flex items-center gap-3">
@@ -108,13 +108,15 @@ export function LatestScripts({
height={64} height={64}
width={64} width={64}
alt="" alt=""
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
className="h-11 w-11 object-contain" className="h-11 w-11 object-contain"
/> />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-lg line-clamp-1"> <p className="text-lg line-clamp-1">
{script.name} {getDisplayValueFromType(script.type)} {script.name}
{" "}
{getDisplayValueFromType(script.type)}
</p> </p>
<p className="text-sm text-muted-foreground flex items-center gap-1"> <p className="text-sm text-muted-foreground flex items-center gap-1">
<CalendarPlus className="h-4 w-4" /> <CalendarPlus className="h-4 w-4" />
@@ -147,7 +149,7 @@ export function LatestScripts({
export function MostViewedScripts({ items }: { items: Category[] }) { export function MostViewedScripts({ items }: { items: Category[] }) {
const mostViewedScripts = items.reduce((acc: Script[], category) => { const mostViewedScripts = items.reduce((acc: Script[], category) => {
const foundScripts = category.scripts.filter((script) => mostPopularScripts.includes(script.slug)); const foundScripts = category.scripts.filter(script => mostPopularScripts.includes(script.slug));
return acc.concat(foundScripts); return acc.concat(foundScripts);
}, []); }, []);
@@ -159,7 +161,7 @@ export function MostViewedScripts({ items }: { items: Category[] }) {
</> </>
)} )}
<div className="min-w flex w-full flex-row flex-wrap gap-4"> <div className="min-w flex w-full flex-row flex-wrap gap-4">
{mostViewedScripts.map((script) => ( {mostViewedScripts.map(script => (
<Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30"> <Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center gap-3"> <CardTitle className="flex items-center gap-3">
@@ -170,13 +172,15 @@ export function MostViewedScripts({ items }: { items: Category[] }) {
height={64} height={64}
width={64} width={64}
alt="" alt=""
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
className="h-11 w-11 object-contain" className="h-11 w-11 object-contain"
/> />
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<p className="line-clamp-1 text-lg"> <p className="line-clamp-1 text-lg">
{script.name} {getDisplayValueFromType(script.type)} {script.name}
{" "}
{getDisplayValueFromType(script.type)}
</p> </p>
<p className="flex items-center gap-1 text-sm text-muted-foreground"> <p className="flex items-center gap-1 text-sm text-muted-foreground">
<CalendarPlus className="h-4 w-4" /> <CalendarPlus className="h-4 w-4" />

View File

@@ -14,7 +14,6 @@ import { basePath } from "@/config/site-config";
import { extractDate } from "@/lib/time"; import { extractDate } from "@/lib/time";
import DisableDescription from "./script-items/disable-description"; import DisableDescription from "./script-items/disable-description";
import { formattedBadge } from "@/components/command-menu";
import { getDisplayValueFromType } from "./script-info-blocks"; import { getDisplayValueFromType } from "./script-info-blocks";
import DefaultPassword from "./script-items/default-password"; import DefaultPassword from "./script-items/default-password";
import InstallCommand from "./script-items/install-command"; import InstallCommand from "./script-items/install-command";
@@ -32,7 +31,7 @@ type ScriptItemProps = {
function ScriptHeader({ item }: { item: Script }) { function ScriptHeader({ item }: { item: Script }) {
const defaultInstallMethod = item.install_methods?.[0]; const defaultInstallMethod = item.install_methods?.[0];
const os = defaultInstallMethod?.resources?.os || (item.type === "addon" ? "Existing LXC or Proxmox Node" : "Proxmox Node"); const os = defaultInstallMethod?.resources?.os || "Proxmox Node";
const version = defaultInstallMethod?.resources?.version || ""; const version = defaultInstallMethod?.resources?.version || "";
return ( return (
@@ -56,7 +55,9 @@ function ScriptHeader({ item }: { item: Script }) {
<h1 className="text-2xl font-semibold tracking-tight flex items-center gap-2"> <h1 className="text-2xl font-semibold tracking-tight flex items-center gap-2">
{item.name} {item.name}
<VersionInfo item={item} /> <VersionInfo item={item} />
{formattedBadge(item.type)} <span className="inline-flex items-center rounded-md bg-accent/30 px-2 py-1 text-sm">
{getDisplayValueFromType(item.type)}
</span>
</h1> </h1>
<div className="mt-1 flex items-center gap-3 text-sm text-muted-foreground"> <div className="mt-1 flex items-center gap-3 text-sm text-muted-foreground">
<span> <span>

View File

@@ -36,24 +36,17 @@ const TooltipBadge: React.FC<TooltipProps> = ({ variant, label, content }) => (
export default function Tooltips({ item }: { item: Script }) { export default function Tooltips({ item }: { item: Script }) {
return ( return (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{item.privileged && item.type !== "addon" && ( {item.privileged && (
<TooltipBadge variant="warning" label="Privileged" content="This script will be run in a privileged LXC" /> <TooltipBadge variant="warning" label="Privileged" content="This script will be run in a privileged LXC" />
)} )}
{item.updateable && item.type !== "pve" && item.type !== "addon" && ( {item.updateable && item.type !== "pve" && (
<TooltipBadge <TooltipBadge
variant="success" variant="success"
label="Updateable" label="Updateable"
content={`To Update ${item.name}, run the command below (or type update) in the LXC Console.`} content={`To Update ${item.name}, run the command below (or type update) in the LXC Console.`}
/> />
)} )}
{item.updateable && item.type === "addon" && ( {!item.updateable && item.type !== "pve" && <TooltipBadge variant="failure" label="Not Updateable" />}
<TooltipBadge
variant="success"
label="Updateable"
content={`Run update_${item.slug} to update or use the bash command inside the LXC.`}
/>
)}
{!item.updateable && item.type !== "pve" && item.type !== "addon" && <TooltipBadge variant="failure" label="Not Updateable" />}
</div> </div>
); );
} }

View File

@@ -32,11 +32,6 @@ function ScriptContent() {
.flat() .flat()
.find(script => script.slug === selectedScript); .find(script => script.slug === selectedScript);
setItem(script); setItem(script);
if (script) {
document.title = `${script.name} | Proxmox VE Helper-Scripts`;
}
} else {
document.title = "Proxmox VE Helper-Scripts";
} }
}, [selectedScript, links]); }, [selectedScript, links]);

View File

@@ -1,7 +1,6 @@
import { ArrowRightIcon, Sparkles } from "lucide-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { ArrowRightIcon, Sparkles } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link";
import React from "react"; import React from "react";
import type { Category, Script } from "@/lib/types"; import type { Category, Script } from "@/lib/types";
@@ -22,6 +21,35 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/t
import { DialogTitle } from "./ui/dialog"; import { DialogTitle } from "./ui/dialog";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
import { Badge } from "./ui/badge"; import { Badge } from "./ui/badge";
import Link from "next/link";
export function search(scripts: Script[], query: string): Script[] {
const queryLower = query.toLowerCase().trim();
const searchWords = queryLower.split(/\s+/).filter(Boolean);
return scripts
.map(script => {
const nameLower = script.name.toLowerCase();
const descriptionLower = (script.description || "").toLowerCase();
let score = 0;
for (const word of searchWords) {
if (nameLower.includes(word)) {
score += 10;
}
if (descriptionLower.includes(word)) {
score += 5;
}
}
return { script, score };
})
.filter(({ score }) => score > 0)
.sort((a, b) => b.score - a.score)
.slice(0, 20)
.map(({ script }) => script);
}
export function formattedBadge(type: string) { export function formattedBadge(type: string) {
switch (type) { switch (type) {
@@ -51,9 +79,11 @@ function getRandomScript(categories: Category[], previouslySelected: Set<string>
} }
function CommandMenu() { function CommandMenu() {
const [query, setQuery] = React.useState("");
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [links, setLinks] = React.useState<Category[]>([]); const [links, setLinks] = React.useState<Category[]>([]);
const [isLoading, setIsLoading] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false);
const [results, setResults] = React.useState<Script[]>([]);
const [selectedScripts, setSelectedScripts] = React.useState<Set<string>>(new Set()); const [selectedScripts, setSelectedScripts] = React.useState<Set<string>>(new Set());
const router = useRouter(); const router = useRouter();
@@ -70,6 +100,27 @@ function CommandMenu() {
}); });
}; };
React.useEffect(() => {
if (query.trim() === "") {
fetchSortedCategories();
}
else {
const scriptMap = new Map<string, Script>();
for (const category of links) {
for (const script of category.scripts || []) {
if (!scriptMap.has(script.slug)) {
scriptMap.set(script.slug, script);
}
}
}
const uniqueScripts = Array.from(scriptMap.values());
const filteredResults = search(uniqueScripts, query);
setResults(filteredResults);
}
}, [query]);
React.useEffect(() => { React.useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) { if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
@@ -197,49 +248,46 @@ function CommandMenu() {
<CommandDialog <CommandDialog
open={open} open={open}
onOpenChange={setOpen} onOpenChange={(open) => {
filter={(value: string, search: string) => { setOpen(open);
const searchLower = search.toLowerCase().trim(); if (open) {
if (!searchLower) setQuery("");
return 1; setResults([]);
const valueLower = value.toLowerCase(); }
const searchWords = searchLower.split(/\s+/).filter(Boolean);
// All search words must appear somewhere in the value (name + description)
const allWordsMatch = searchWords.every((word: string) => valueLower.includes(word));
return allWordsMatch ? 1 : 0;
}} }}
> >
<DialogTitle className="sr-only">Search scripts</DialogTitle> <DialogTitle className="sr-only">Search scripts</DialogTitle>
<CommandInput placeholder="Search for a script..." /> <CommandInput
placeholder="Search for a script..."
onValueChange={setQuery}
value={query}
/>
<CommandList> <CommandList>
<CommandEmpty> <CommandEmpty>
{isLoading {isLoading ? (
? ( "Searching..."
"Searching..." ) : (
) <div className="flex flex-col items-center justify-center py-6 text-center">
: ( <p className="text-sm text-muted-foreground">No scripts match your search.</p>
<div className="flex flex-col items-center justify-center py-6 text-center"> <div className="mt-4">
<p className="text-sm text-muted-foreground">No scripts match your search.</p> <p className="text-xs text-muted-foreground mb-2">Want to add a new script?</p>
<div className="mt-4"> <Button variant="outline" size="sm" asChild>
<p className="text-xs text-muted-foreground mb-2">Want to add a new script?</p> <Link
<Button variant="outline" size="sm" asChild> href={`https://github.com/community-scripts/${basePath}/tree/main/docs/contribution/GUIDE.md`}
<Link target="_blank"
href={`https://github.com/community-scripts/${basePath}/tree/main/docs/contribution/GUIDE.md`} rel="noopener noreferrer"
target="_blank" >
rel="noopener noreferrer" Documentation <ArrowRightIcon className="ml-2 h-4 w-4" />
> </Link>
Documentation </Button>
{" "} </div>
<ArrowRightIcon className="ml-2 h-4 w-4" /> </div>
</Link> )}
</Button>
</div>
</div>
)}
</CommandEmpty> </CommandEmpty>
{Object.entries(uniqueScriptsByCategory).map(([categoryName, scripts]) => (
<CommandGroup key={`category:${categoryName}`} heading={categoryName}> {results.length > 0 ? (
{scripts.map(script => ( <CommandGroup heading="Search Results">
{results.map(script => (
<CommandItem <CommandItem
key={`script:${script.slug}`} key={`script:${script.slug}`}
value={`${script.name} ${script.type} ${script.description || ""}`} value={`${script.name} ${script.type} ${script.description || ""}`}
@@ -272,7 +320,44 @@ function CommandMenu() {
</CommandItem> </CommandItem>
))} ))}
</CommandGroup> </CommandGroup>
))} ) : ( // When no search results, show all scripts grouped by category
Object.entries(uniqueScriptsByCategory).map(([categoryName, scripts]) => (
<CommandGroup key={`category:${categoryName}`} heading={categoryName}>
{scripts.map(script => (
<CommandItem
key={`script:${script.slug}`}
value={`${script.name} ${script.type} ${script.description || ""}`}
onSelect={() => {
setOpen(false);
router.push(`/scripts?id=${script.slug}`);
}}
tabIndex={0}
aria-label={`Open script ${script.name}`}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
setOpen(false);
router.push(`/scripts?id=${script.slug}`);
}
}}
>
<div className="flex gap-2" onClick={() => setOpen(false)}>
<Image
src={script.logo || `/${basePath}/logo.png`}
onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
unoptimized
width={16}
height={16}
alt=""
className="h-5 w-5"
/>
<span>{script.name}</span>
<span>{formattedBadge(script.type)}</span>
</div>
</CommandItem>
))}
</CommandGroup>
))
)}
</CommandList> </CommandList>
</CommandDialog> </CommandDialog>
</> </>

View File

@@ -0,0 +1,75 @@
#!/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://komo.do/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apk add --no-cache ca-certificates openssl
msg_ok "Installed Dependencies"
msg_info "Setup Docker Repository"
$STD apk add --no-cache docker docker-cli docker-compose openrc
msg_ok "Setup Docker Repository"
msg_info "Enabling Docker Service"
$STD rc-update add docker boot
$STD service docker start
msg_ok "Enabled Docker Service"
echo "${TAB3}Choose the database for Komodo installation:"
echo "${TAB3}1) MongoDB (recommended)"
echo "${TAB3}2) FerretDB"
read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in
1)
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
2)
DB_COMPOSE_FILE="ferretdb.compose.yaml"
;;
*)
echo "Invalid choice. Defaulting to MongoDB."
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
esac
mkdir -p /opt/komodo
cd /opt/komodo
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/$DB_COMPOSE_FILE" -o "$(basename "$DB_COMPOSE_FILE")"
msg_info "Setup Komodo Environment"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env" -o "/opt/komodo/compose.env"
DB_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
PASSKEY=$(openssl rand -base64 24 | tr -d '/+=')
WEBHOOK_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
JWT_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
sed -i "s/^KOMODO_DB_USERNAME=.*/KOMODO_DB_USERNAME=komodo_admin/" /opt/komodo/compose.env
sed -i "s/^KOMODO_DB_PASSWORD=.*/KOMODO_DB_PASSWORD=${DB_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_PASSKEY=.*/KOMODO_PASSKEY=${PASSKEY}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_WEBHOOK_SECRET=.*/KOMODO_WEBHOOK_SECRET=${WEBHOOK_SECRET}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_JWT_SECRET=.*/KOMODO_JWT_SECRET=${JWT_SECRET}/" /opt/komodo/compose.env
msg_ok "Setup Komodo Environment"
msg_info "Initialize Komodo"
$STD docker compose -p komodo -f "/opt/komodo/$DB_COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Initialized Komodo"
motd_ssh
customize
msg_info "Cleaning up"
$STD apk cache clean
msg_ok "Cleaned"

View File

@@ -14,7 +14,7 @@ network_check
update_os update_os
read -r -p "${TAB3}Enter PostgreSQL version (15/16/17): " ver read -r -p "${TAB3}Enter PostgreSQL version (15/16/17): " ver
[[ $ver =~ ^(15|16|17)$ ]] || { echo "Invalid version"; exit 64; } [[ $ver =~ ^(15|16|17)$ ]] || { echo "Invalid version"; exit 1; }
msg_info "Installing PostgreSQL ${ver}" msg_info "Installing PostgreSQL ${ver}"
$STD apk add --no-cache postgresql${ver} postgresql${ver}-contrib postgresql${ver}-openrc sudo $STD apk add --no-cache postgresql${ver} postgresql${ver}-contrib postgresql${ver}-openrc sudo

View File

@@ -36,9 +36,9 @@ msg_ok "Installed Tinyauth"
read -r -p "${TAB3}Enter your Tinyauth subdomain (e.g. https://tinyauth.example.com): " app_url read -r -p "${TAB3}Enter your Tinyauth subdomain (e.g. https://tinyauth.example.com): " app_url
cat <<EOF >/opt/tinyauth/.env cat <<EOF >/opt/tinyauth/.env
TINYAUTH_DATABASE_PATH=/opt/tinyauth/database.db DATABASE_PATH=/opt/tinyauth/database.db
TINYAUTH_AUTH_USERS='${USER}' USERS='${USER}'
TINYAUTH_APPURL=${app_url} APP_URL=${app_url}
EOF EOF
msg_info "Creating Service" msg_info "Creating Service"

View File

@@ -25,7 +25,7 @@ case $version in
;; ;;
*) *)
msg_error "Invalid JDK version selected. Please enter 8, 11, 17 or 21." msg_error "Invalid JDK version selected. Please enter 8, 11, 17 or 21."
exit 64 exit 1
;; ;;
esac esac
;; ;;
@@ -39,7 +39,7 @@ case $version in
;; ;;
*) *)
msg_error "Invalid JDK version selected. Please enter 11, 17 or 21." msg_error "Invalid JDK version selected. Please enter 11, 17 or 21."
exit 64 exit 1
;; ;;
esac esac
;; ;;
@@ -53,13 +53,13 @@ case $version in
;; ;;
*) *)
msg_error "Invalid JDK version selected. Please enter 17 or 21." msg_error "Invalid JDK version selected. Please enter 17 or 21."
exit 64 exit 1
;; ;;
esac esac
;; ;;
*) *)
msg_error "Invalid Tomcat version selected. Please enter 9, 10.1 or 11." msg_error "Invalid Tomcat version selected. Please enter 9, 10.1 or 11."
exit 64 exit 1
;; ;;
esac esac

View File

@@ -13,10 +13,6 @@ setting_up_container
network_check network_check
update_os update_os
msg_info "Installing Dependencies"
$STD apt install -y ffmpeg
msg_ok "Installed Dependencies"
JAVA_VERSION="25" setup_java JAVA_VERSION="25" setup_java
NODE_VERSION="22" setup_nodejs NODE_VERSION="22" setup_nodejs
setup_mariadb setup_mariadb
@@ -59,7 +55,7 @@ mkdir -p /opt/booklore/dist
JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1) JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1)
if [[ -z "$JAR_PATH" ]]; then if [[ -z "$JAR_PATH" ]]; then
msg_error "Backend JAR not found" msg_error "Backend JAR not found"
exit 153 exit 1
fi fi
cp "$JAR_PATH" /opt/booklore/dist/app.jar cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend" msg_ok "Built Backend"
@@ -74,7 +70,7 @@ After=network.target mariadb.service
Type=simple Type=simple
User=root User=root
WorkingDirectory=/opt/booklore/dist WorkingDirectory=/opt/booklore/dist
ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError -jar /opt/booklore/dist/app.jar ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -jar /opt/booklore/dist/app.jar
EnvironmentFile=/opt/booklore_storage/.env EnvironmentFile=/opt/booklore_storage/.env
SuccessExitStatus=143 SuccessExitStatus=143
TimeoutStopSec=10 TimeoutStopSec=10

View File

@@ -39,7 +39,7 @@ $STD apt install -y \
texlive-xetex texlive-xetex
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="bun" setup_nodejs NODE_VERSION=22 NODE_MODULE="bun" setup_nodejs
fetch_and_deploy_gh_release "ConvertX" "C4illin/ConvertX" "tarball" "latest" "/opt/convertx" fetch_and_deploy_gh_release "ConvertX" "C4illin/ConvertX" "tarball" "latest" "/opt/convertx"
msg_info "Installing ConvertX" msg_info "Installing ConvertX"

View File

@@ -0,0 +1,39 @@
#!/bin/bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://coolify.io/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
git \
openssl
msg_ok "Installed Dependencies"
msg_warn "WARNING: This script will run an external installer from a third-party source (https://coolify.io/)."
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://cdn.coollabs.io/coolify/install.sh"
echo
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg_error "Aborted by user. No changes have been made."
exit 10
fi
msg_info "Installing Coolify (Patience - this installs Docker and pulls containers)"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Installed Coolify"
motd_ssh
customize
cleanup_lxc

View File

@@ -15,40 +15,14 @@ update_os
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt install -y \ $STD apt install -y \
nginx \ nginx \
valkey \ valkey
mariadb-client \
rclone
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
PG_VERSION="17" setup_postgresql PG_VERSION="17" setup_postgresql
setup_go setup_go
NODE_VERSION="24" setup_nodejs NODE_VERSION="24" setup_nodejs
msg_info "Installing Database Clients"
# Create PostgreSQL version symlinks for compatibility
for v in 12 13 14 15 16 18; do
ln -sf /usr/lib/postgresql/17 /usr/lib/postgresql/$v
done
# Install MongoDB Database Tools via direct .deb (no APT repo for Debian 13)
[[ "$(get_os_info id)" == "ubuntu" ]] && MONGO_DIST="ubuntu2204" || MONGO_DIST="debian12"
MONGO_VERSION=$(get_latest_gh_tag "mongodb/mongo-tools" "100." || echo "100.14.1")
fetch_and_deploy_from_url "https://fastdl.mongodb.org/tools/db/mongodb-database-tools-${MONGO_DIST}-x86_64-${MONGO_VERSION}.deb"
mkdir -p /usr/local/mongodb-database-tools/bin
[[ -f /usr/bin/mongodump ]] && ln -sf /usr/bin/mongodump /usr/local/mongodb-database-tools/bin/mongodump
[[ -f /usr/bin/mongorestore ]] && ln -sf /usr/bin/mongorestore /usr/local/mongodb-database-tools/bin/mongorestore
# Create MariaDB and MySQL client symlinks for compatibility
mkdir -p /usr/local/mariadb-{10.6,12.1}/bin /usr/local/mysql-{5.7,8.0,8.4,9}/bin
for dir in /usr/local/mariadb-{10.6,12.1}/bin; do
ln -sf /usr/bin/mariadb-dump "$dir/mariadb-dump"
ln -sf /usr/bin/mariadb "$dir/mariadb"
done
for dir in /usr/local/mysql-{5.7,8.0,8.4,9}/bin; do
ln -sf /usr/bin/mariadb-dump "$dir/mysqldump"
ln -sf /usr/bin/mariadb "$dir/mysql"
done
msg_ok "Installed Database Clients"
fetch_and_deploy_gh_release "databasus" "databasus/databasus" "tarball" "latest" "/opt/databasus" fetch_and_deploy_gh_release "databasus" "databasus/databasus" "tarball" "latest" "/opt/databasus"
msg_info "Building Databasus (Patience)" msg_info "Building Databasus (Patience)"
@@ -73,6 +47,10 @@ msg_ok "Built Databasus"
msg_info "Configuring Databasus" msg_info "Configuring Databasus"
JWT_SECRET=$(openssl rand -hex 32) JWT_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32) ENCRYPTION_KEY=$(openssl rand -hex 32)
# Create PostgreSQL version symlinks for compatibility
for v in 12 13 14 15 16 18; do
ln -sf /usr/lib/postgresql/17 /usr/lib/postgresql/$v
done
# Install goose for migrations # Install goose for migrations
$STD go install github.com/pressly/goose/v3/cmd/goose@latest $STD go install github.com/pressly/goose/v3/cmd/goose@latest
ln -sf /root/go/bin/goose /usr/local/bin/goose ln -sf /root/go/bin/goose /usr/local/bin/goose

View File

@@ -16,23 +16,19 @@ update_os
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt install -y \ $STD apt install -y \
build-essential \ build-essential \
cmake \
git \ git \
imagemagick \
libffi-dev \
libgeos-dev \
libgeos++-dev \
libjemalloc2 \
libjemalloc-dev \
libmagickwand-dev \
libpq-dev \ libpq-dev \
libssl-dev \ libgeos-dev \
libvips-dev \
libxml2-dev \
libxslt-dev \
libyaml-dev \ libyaml-dev \
nginx \ libffi-dev \
redis-server libssl-dev \
libjemalloc2 \
imagemagick \
libmagickwand-dev \
libvips-dev \
cmake \
redis-server \
nginx
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
PG_VERSION="17" PG_MODULES="postgis-3" setup_postgresql PG_VERSION="17" PG_MODULES="postgis-3" setup_postgresql
@@ -86,8 +82,7 @@ elif [[ -f /opt/dawarich/app/package.json ]]; then
$STD npm install $STD npm install
fi fi
$STD bundle exec rake assets:precompile $STD bundle exec rake assets:precompile
$STD bundle exec rails db:schema:load $STD bundle exec rails db:prepare
$STD bundle exec rails db:seed || msg_warn "Database seed failed (upstream rgeo-geojson issue), app will still work"
$STD bundle exec rake data:migrate $STD bundle exec rake data:migrate
msg_ok "Installed Dawarich" msg_ok "Installed Dawarich"

View File

@@ -86,7 +86,7 @@ EOF
msg_ok "Docker TCP socket available on $socket" msg_ok "Docker TCP socket available on $socket"
else else
msg_error "Docker failed to restart. Check journalctl -xeu docker.service" msg_error "Docker failed to restart. Check journalctl -xeu docker.service"
exit 150 exit 1
fi fi
fi fi

64
install/dockge-install.sh Normal file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dockge.kuma.pet/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
DOCKER_LATEST_VERSION=$(get_latest_github_release "moby/moby")
msg_info "Installing Docker $DOCKER_LATEST_VERSION (with Compose, Buildx)"
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p $(dirname $DOCKER_CONFIG_PATH)
echo -e '{\n "log-driver": "journald"\n}' >/etc/docker/daemon.json
$STD sh <(curl -fsSL https://get.docker.com)
msg_ok "Installed Docker $DOCKER_LATEST_VERSION"
msg_info "Installing Dockge"
mkdir -p /opt/{dockge,stacks}
curl -fsSL "https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml" -o "/opt/dockge/compose.yaml"
cd /opt/dockge
$STD docker compose up -d
msg_ok "Installed Dockge"
read -r -p "${TAB3}Would you like to add Immich? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Immich compose.yaml"
mkdir -p /opt/stacks/immich
curl -fsSL "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml" -o "/opt/stacks/immich/compose.yaml"
curl -fsSL "https://github.com/immich-app/immich/releases/latest/download/example.env" -o "/opt/stacks/immich/.env"
msg_ok "Added Immich compose.yaml"
fi
read -r -p "${TAB3}Would you like to add Home Assistant? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Home Assistant compose.yaml"
mkdir -p /opt/stacks/homeassistant
cat <<EOF >/opt/stacks/homeassistant/compose.yaml
version: "3"
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
privileged: true
network_mode: host
EOF
msg_ok "Added Home Assistant compose.yaml"
fi
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dokploy.com/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
git \
openssl \
redis
msg_ok "Installed Dependencies"
msg_warn "WARNING: This script will run an external installer from a third-party source (https://dokploy.com/)."
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://dokploy.com/install.sh"
echo
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg_error "Aborted by user. No changes have been made."
exit 10
fi
msg_info "Installing Dokploy (Patience - this installs Docker and pulls containers)"
$STD bash <(curl -sSL https://dokploy.com/install.sh)
msg_ok "Installed Dokploy"
motd_ssh
customize
cleanup_lxc

View File

@@ -21,7 +21,7 @@ msg_info "Fetching latest EMQX Enterprise version"
LATEST_VERSION=$(curl -fsSL https://www.emqx.com/en/downloads/enterprise | grep -oP '/en/downloads/enterprise/v\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n1) LATEST_VERSION=$(curl -fsSL https://www.emqx.com/en/downloads/enterprise | grep -oP '/en/downloads/enterprise/v\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n1)
if [[ -z "$LATEST_VERSION" ]]; then if [[ -z "$LATEST_VERSION" ]]; then
msg_error "Failed to determine latest EMQX version" msg_error "Failed to determine latest EMQX version"
exit 250 exit 1
fi fi
msg_ok "Latest version: v$LATEST_VERSION" msg_ok "Latest version: v$LATEST_VERSION"

View File

@@ -72,7 +72,7 @@ cat <<EOF >/etc/apache2/sites-available/firefly.conf
</VirtualHost> </VirtualHost>
EOF EOF
chown www-data:www-data /opt/firefly/storage/oauth-*.key chown www-data:www-data /opt/firefly/storage/oauth-*.key
$STD a2enmod php8.5 $STD a2enmod php8.4
$STD a2enmod rewrite $STD a2enmod rewrite
$STD a2ensite firefly.conf $STD a2ensite firefly.conf
$STD a2dissite 000-default.conf $STD a2dissite 000-default.conf

View File

@@ -1,7 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG # Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ) | Co-Authors: remz1337 # Authors: MickLesk (CanbiZ)
# Co-Authors: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/ | Github: https://github.com/blakeblackshear/frigate # Source: https://frigate.video/ | Github: https://github.com/blakeblackshear/frigate
@@ -16,7 +17,7 @@ update_os
source /etc/os-release source /etc/os-release
if [[ "$VERSION_ID" != "12" ]]; then if [[ "$VERSION_ID" != "12" ]]; then
msg_error "Frigate requires Debian 12 (Bookworm) due to Python 3.11 dependencies" msg_error "Frigate requires Debian 12 (Bookworm) due to Python 3.11 dependencies"
exit 238 exit 1
fi fi
msg_info "Converting APT sources to DEB822 format" msg_info "Converting APT sources to DEB822 format"
@@ -84,7 +85,6 @@ $STD apt install -y \
tclsh \ tclsh \
libopenblas-dev \ libopenblas-dev \
liblapack-dev \ liblapack-dev \
libgomp1 \
make \ make \
moreutils moreutils
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
@@ -101,16 +101,9 @@ export NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
export TOKENIZERS_PARALLELISM=true export TOKENIZERS_PARALLELISM=true
export TRANSFORMERS_NO_ADVISORY_WARNINGS=1 export TRANSFORMERS_NO_ADVISORY_WARNINGS=1
export OPENCV_FFMPEG_LOGLEVEL=8 export OPENCV_FFMPEG_LOGLEVEL=8
export PYTHONWARNINGS="ignore:::numpy.core.getlimits"
export HAILORT_LOGGER_PATH=NONE export HAILORT_LOGGER_PATH=NONE
export TF_CPP_MIN_LOG_LEVEL=3
export TF_CPP_MIN_VLOG_LEVEL=3
export TF_ENABLE_ONEDNN_OPTS=0
export AUTOGRAPH_VERBOSITY=0
export GLOG_minloglevel=3
export GLOG_logtostderr=0
fetch_and_deploy_gh_release "frigate" "blakeblackshear/frigate" "tarball" "v0.17.0" "/opt/frigate" fetch_and_deploy_gh_release "frigate" "blakeblackshear/frigate" "tarball" "v0.16.4" "/opt/frigate"
msg_info "Building Nginx" msg_info "Building Nginx"
$STD bash /opt/frigate/docker/main/build_nginx.sh $STD bash /opt/frigate/docker/main/build_nginx.sh
@@ -145,19 +138,13 @@ install -c -m 644 libusb-1.0.pc /usr/local/lib/pkgconfig
ldconfig ldconfig
msg_ok "Built libUSB" msg_ok "Built libUSB"
msg_info "Bootstrapping pip"
wget -q https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py
sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' /tmp/get-pip.py
$STD python3 /tmp/get-pip.py "pip"
rm -f /tmp/get-pip.py
msg_ok "Bootstrapped pip"
msg_info "Installing Python Dependencies" msg_info "Installing Python Dependencies"
$STD pip3 install -r /opt/frigate/docker/main/requirements.txt $STD pip3 install -r /opt/frigate/docker/main/requirements.txt
msg_ok "Installed Python Dependencies" msg_ok "Installed Python Dependencies"
msg_info "Building Python Wheels (Patience)" msg_info "Building Python Wheels (Patience)"
mkdir -p /wheels mkdir -p /wheels
sed -i 's|^SQLITE3_VERSION=.*|SQLITE3_VERSION="version-3.46.0"|g' /opt/frigate/docker/main/build_pysqlite3.sh
$STD bash /opt/frigate/docker/main/build_pysqlite3.sh $STD bash /opt/frigate/docker/main/build_pysqlite3.sh
for i in {1..3}; do for i in {1..3}; do
$STD pip3 wheel --wheel-dir=/wheels -r /opt/frigate/docker/main/requirements-wheels.txt --default-timeout=300 --retries=3 && break $STD pip3 wheel --wheel-dir=/wheels -r /opt/frigate/docker/main/requirements-wheels.txt --default-timeout=300 --retries=3 && break
@@ -165,7 +152,7 @@ for i in {1..3}; do
done done
msg_ok "Built Python Wheels" msg_ok "Built Python Wheels"
NODE_VERSION="20" setup_nodejs NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
msg_info "Downloading Inference Models" msg_info "Downloading Inference Models"
mkdir -p /models /openvino-model mkdir -p /models /openvino-model
@@ -196,10 +183,6 @@ $STD pip3 install -U /wheels/*.whl
ldconfig ldconfig
msg_ok "Installed HailoRT Runtime" msg_ok "Installed HailoRT Runtime"
msg_info "Installing MemryX Runtime"
$STD bash /opt/frigate/docker/main/install_memryx.sh
msg_ok "Installed MemryX Runtime"
msg_info "Installing OpenVino" msg_info "Installing OpenVino"
$STD pip3 install -r /opt/frigate/docker/main/requirements-ov.txt $STD pip3 install -r /opt/frigate/docker/main/requirements-ov.txt
msg_ok "Installed OpenVino" msg_ok "Installed OpenVino"
@@ -226,8 +209,6 @@ $STD make version
cd /opt/frigate/web cd /opt/frigate/web
$STD npm install $STD npm install
$STD npm run build $STD npm run build
mv /opt/frigate/web/dist/BASE_PATH/monacoeditorwork/* /opt/frigate/web/dist/assets/
rm -rf /opt/frigate/web/dist/BASE_PATH
cp -r /opt/frigate/web/dist/* /opt/frigate/web/ cp -r /opt/frigate/web/dist/* /opt/frigate/web/
sed -i '/^s6-svc -O \.$/s/^/#/' /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run sed -i '/^s6-svc -O \.$/s/^/#/' /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
msg_ok "Built Frigate Application" msg_ok "Built Frigate Application"
@@ -243,19 +224,6 @@ echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab
cat <<EOF >/etc/frigate.env cat <<EOF >/etc/frigate.env
DEFAULT_FFMPEG_VERSION="7.0" DEFAULT_FFMPEG_VERSION="7.0"
INCLUDED_FFMPEG_VERSIONS="7.0:5.0" INCLUDED_FFMPEG_VERSIONS="7.0:5.0"
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
TOKENIZERS_PARALLELISM=true
TRANSFORMERS_NO_ADVISORY_WARNINGS=1
OPENCV_FFMPEG_LOGLEVEL=8
PYTHONWARNINGS="ignore:::numpy.core.getlimits"
HAILORT_LOGGER_PATH=NONE
TF_CPP_MIN_LOG_LEVEL=3
TF_CPP_MIN_VLOG_LEVEL=3
TF_ENABLE_ONEDNN_OPTS=0
AUTOGRAPH_VERBOSITY=0
GLOG_minloglevel=3
GLOG_logtostderr=0
EOF EOF
cat <<EOF >/config/config.yml cat <<EOF >/config/config.yml
@@ -269,6 +237,7 @@ cameras:
input_args: -re -stream_loop -1 -fflags +genpts input_args: -re -stream_loop -1 -fflags +genpts
roles: roles:
- detect - detect
- rtmp
detect: detect:
height: 1080 height: 1080
width: 1920 width: 1920
@@ -286,7 +255,6 @@ ffmpeg:
detectors: detectors:
detector01: detector01:
type: openvino type: openvino
device: AUTO
model: model:
width: 300 width: 300
height: 300 height: 300

View File

@@ -76,20 +76,6 @@ source /opt/gramps-web/venv/bin/activate
$STD uv pip install --no-cache-dir --upgrade pip setuptools wheel $STD uv pip install --no-cache-dir --upgrade pip setuptools wheel
$STD uv pip install --no-cache-dir gunicorn $STD uv pip install --no-cache-dir gunicorn
$STD uv pip install --no-cache-dir /opt/gramps-web-api $STD uv pip install --no-cache-dir /opt/gramps-web-api
GRAMPS_VERSION=$(/opt/gramps-web/venv/bin/python3 -c "import gramps.version; print('%s%s' % (gramps.version.VERSION_TUPLE[0], gramps.version.VERSION_TUPLE[1]))" 2>/dev/null || echo "60")
GRAMPS_PLUGINS_DIR="/opt/gramps-web/data/gramps/gramps${GRAMPS_VERSION}/plugins"
mkdir -p "$GRAMPS_PLUGINS_DIR"
msg_info "Installing Gramps Addons (gramps${GRAMPS_VERSION})"
$STD wget -q https://github.com/gramps-project/addons/archive/refs/heads/master.zip -O /tmp/gramps-addons.zip
for addon in FilterRules JSON; do
unzip -p /tmp/gramps-addons.zip "addons-master/gramps${GRAMPS_VERSION}/download/${addon}.addon.tgz" | \
tar -xz -C "$GRAMPS_PLUGINS_DIR"
done
rm -f /tmp/gramps-addons.zip
msg_ok "Installed Gramps Addons"
cd /opt/gramps-web/frontend cd /opt/gramps-web/frontend
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
$STD corepack enable $STD corepack enable
@@ -98,7 +84,7 @@ $STD npm run build
cd /opt/gramps-web-api cd /opt/gramps-web-api
GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \ GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \
ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \ ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \
GRAMPSHOME=/opt/gramps-web/data \ GRAMPSHOME=/opt/gramps-web/data/gramps \
GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \ GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \
$STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate $STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate
msg_ok "Set up Gramps Web" msg_ok "Set up Gramps Web"
@@ -114,7 +100,7 @@ Type=simple
User=root User=root
WorkingDirectory=/opt/gramps-web-api WorkingDirectory=/opt/gramps-web-api
Environment=GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg Environment=GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg
Environment=GRAMPSHOME=/opt/gramps-web/data Environment=GRAMPSHOME=/opt/gramps-web/data/gramps
Environment=GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb Environment=GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb
Environment=PATH=/opt/gramps-web/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin Environment=PATH=/opt/gramps-web/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=/opt/gramps-web/venv/bin/gunicorn -w 2 -b 0.0.0.0:5000 gramps_webapi.wsgi:app --timeout 120 --limit-request-line 8190 ExecStart=/opt/gramps-web/venv/bin/gunicorn -w 2 -b 0.0.0.0:5000 gramps_webapi.wsgi:app --timeout 120 --limit-request-line 8190

View File

@@ -32,9 +32,9 @@ if [ -d /dev/dri ]; then
$STD apt install -y --no-install-recommends patchelf $STD apt install -y --no-install-recommends patchelf
tmp_dir=$(mktemp -d) tmp_dir=$(mktemp -d)
$STD pushd "$tmp_dir" $STD pushd "$tmp_dir"
curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile curl -fsSLO https://raw.githubusercontent.com/immich-app/base-images/refs/heads/main/server/Dockerfile
readarray -t INTEL_URLS < <( readarray -t INTEL_URLS < <(
sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $3}' sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $2}'
sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}' sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}'
) )
for url in "${INTEL_URLS[@]}"; do for url in "${INTEL_URLS[@]}"; do
@@ -150,11 +150,11 @@ PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql
VCHORD_RELEASE="0.5.3" VCHORD_RELEASE="0.5.3"
fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-16-vchord_*_amd64.deb" fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-16-vchord_*_amd64.deb"
sed -i "s/^#shared_preload.*/shared_preload_libraries = 'vchord.so'/" /etc/postgresql/16/main/postgresql.conf sed -i -e "/^#shared_preload/s/^#//;/^shared_preload/s/''/'vchord.so'/" /etc/postgresql/16/main/postgresql.conf
systemctl restart postgresql.service systemctl restart postgresql.service
PG_DB_NAME="immich" PG_DB_USER="immich" PG_DB_GRANT_SUPERUSER="true" PG_DB_SKIP_ALTER_ROLE="true" setup_postgresql_db PG_DB_NAME="immich" PG_DB_USER="immich" PG_DB_GRANT_SUPERUSER="true" PG_DB_SKIP_ALTER_ROLE="true" setup_postgresql_db
msg_warn "Compiling Custom Photo-processing Libraries (can take anywhere from 15min to 2h)" msg_info "Compiling Custom Photo-processing Library (extreme patience)"
LD_LIBRARY_PATH=/usr/local/lib LD_LIBRARY_PATH=/usr/local/lib
export LD_RUN_PATH=/usr/local/lib export LD_RUN_PATH=/usr/local/lib
STAGING_DIR=/opt/staging STAGING_DIR=/opt/staging
@@ -342,9 +342,9 @@ mkdir -p "$ML_DIR" && chown -R immich:immich "$INSTALL_DIR"
export VIRTUAL_ENV="${ML_DIR}/ml-venv" export VIRTUAL_ENV="${ML_DIR}/ml-venv"
if [[ -f ~/.openvino ]]; then if [[ -f ~/.openvino ]]; then
msg_info "Installing HW-accelerated machine-learning" msg_info "Installing HW-accelerated machine-learning"
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p python3.13 --managed-python $STD uv add --no-sync --optional openvino onnxruntime-openvino==1.20.0 --active -n -p python3.12 --managed-python
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.13 --managed-python $STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.12 --managed-python
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-x86_64-linux-gnu.so" patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.12/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-312-x86_64-linux-gnu.so"
msg_ok "Installed HW-accelerated machine-learning" msg_ok "Installed HW-accelerated machine-learning"
else else
msg_info "Installing machine-learning" msg_info "Installing machine-learning"

View File

@@ -21,7 +21,7 @@ msg_ok "Installed Dependencies"
PG_VERSION="17" setup_postgresql PG_VERSION="17" setup_postgresql
PG_DB_NAME="joplin" PG_DB_USER="joplin" setup_postgresql_db PG_DB_NAME="joplin" PG_DB_USER="joplin" setup_postgresql_db
NODE_VERSION="24" NODE_MODULE="yarn,npm,pm2" setup_nodejs NODE_VERSION=24 NODE_MODULE="yarn,npm,pm2" setup_nodejs
mkdir -p /opt/pm2 mkdir -p /opt/pm2
export PM2_HOME=/opt/pm2 export PM2_HOME=/opt/pm2
$STD pm2 install pm2-logrotate $STD pm2 install pm2-logrotate

View File

@@ -31,7 +31,7 @@ fi
if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then
msg_error "Unable to detect latest Kasm release URL." msg_error "Unable to detect latest Kasm release URL."
exit 250 exit 1
fi fi
msg_ok "Detected Kasm Workspaces version $KASM_VERSION" msg_ok "Detected Kasm Workspaces version $KASM_VERSION"

View File

@@ -1,212 +0,0 @@
#!/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/Chevron7Locked/kima-hub
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 \
build-essential \
git \
openssl \
ffmpeg \
python3 \
python3-pip \
python3-dev \
python3-numpy \
redis-server
msg_ok "Installed Dependencies"
PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql
PG_DB_NAME="kima" PG_DB_USER="kima" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
NODE_VERSION="20" setup_nodejs
msg_info "Configuring Redis"
systemctl enable -q --now redis-server
msg_ok "Configured Redis"
fetch_and_deploy_gh_release "kima-hub" "Chevron7Locked/kima-hub" "tarball"
msg_info "Installing Python Dependencies"
export PIP_BREAK_SYSTEM_PACKAGES=1
$STD pip3 install --no-cache-dir \
tensorflow \
essentia-tensorflow \
redis \
psycopg2-binary \
laion-clap \
torch \
torchaudio \
librosa \
transformers \
pgvector \
python-dotenv \
requests
msg_ok "Installed Python Dependencies"
msg_info "Downloading Essentia ML Models"
mkdir -p /opt/kima-hub/models
cd /opt/kima-hub/models
curl -fsSL -o msd-musicnn-1.pb "https://essentia.upf.edu/models/autotagging/msd/msd-musicnn-1.pb"
curl -fsSL -o mood_happy-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_happy/mood_happy-msd-musicnn-1.pb"
curl -fsSL -o mood_sad-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_sad/mood_sad-msd-musicnn-1.pb"
curl -fsSL -o mood_relaxed-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_relaxed/mood_relaxed-msd-musicnn-1.pb"
curl -fsSL -o mood_aggressive-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_aggressive/mood_aggressive-msd-musicnn-1.pb"
curl -fsSL -o mood_party-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_party/mood_party-msd-musicnn-1.pb"
curl -fsSL -o mood_acoustic-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_acoustic/mood_acoustic-msd-musicnn-1.pb"
curl -fsSL -o mood_electronic-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_electronic/mood_electronic-msd-musicnn-1.pb"
curl -fsSL -o danceability-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/danceability/danceability-msd-musicnn-1.pb"
curl -fsSL -o voice_instrumental-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/voice_instrumental/voice_instrumental-msd-musicnn-1.pb"
msg_ok "Downloaded Essentia ML Models"
msg_info "Downloading CLAP Model"
curl -fsSL -o /opt/kima-hub/models/music_audioset_epoch_15_esc_90.14.pt "https://huggingface.co/lukewys/laion_clap/resolve/main/music_audioset_epoch_15_esc_90.14.pt"
msg_ok "Downloaded CLAP Model"
msg_info "Building Backend"
cd /opt/kima-hub/backend
$STD npm ci
$STD npm run build
msg_ok "Built Backend"
msg_info "Configuring Backend"
SESSION_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
cat <<EOF >/opt/kima-hub/backend/.env
NODE_ENV=production
DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
REDIS_URL=redis://localhost:6379
PORT=3006
MUSIC_PATH=/music
TRANSCODE_CACHE_PATH=/opt/kima-hub/cache/transcodes
SESSION_SECRET=${SESSION_SECRET}
SETTINGS_ENCRYPTION_KEY=${ENCRYPTION_KEY}
INTERNAL_API_SECRET=$(openssl rand -hex 16)
EOF
msg_ok "Configured Backend"
msg_info "Running Database Migrations"
cd /opt/kima-hub/backend
$STD npx prisma generate
$STD npx prisma migrate deploy
msg_ok "Ran Database Migrations"
msg_info "Building Frontend"
cd /opt/kima-hub/frontend
$STD npm ci
export NEXT_PUBLIC_BACKEND_URL=http://127.0.0.1:3006
$STD npm run build
msg_ok "Built Frontend"
msg_info "Configuring Frontend"
cat <<EOF >/opt/kima-hub/frontend/.env
NODE_ENV=production
BACKEND_URL=http://localhost:3006
PORT=3030
EOF
msg_ok "Configured Frontend"
msg_info "Creating Directories"
mkdir -p /opt/kima-hub/cache/transcodes
mkdir -p /music
msg_ok "Created Directories"
msg_info "Creating Services"
cat <<EOF >/etc/systemd/system/kima-backend.service
[Unit]
Description=Kima Hub Backend
After=network.target postgresql.service redis-server.service
Wants=postgresql.service redis-server.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/kima-hub/backend
EnvironmentFile=/opt/kima-hub/backend/.env
ExecStart=/usr/bin/node /opt/kima-hub/backend/dist/index.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/systemd/system/kima-frontend.service
[Unit]
Description=Kima Hub Frontend
After=network.target kima-backend.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/kima-hub/frontend
EnvironmentFile=/opt/kima-hub/frontend/.env
ExecStart=/usr/bin/npm start
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/systemd/system/kima-analyzer.service
[Unit]
Description=Kima Hub Audio Analyzer (Essentia)
After=network.target postgresql.service redis-server.service kima-backend.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/kima-hub/services/audio-analyzer
Environment=DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
Environment=REDIS_URL=redis://localhost:6379
Environment=MUSIC_PATH=/music
Environment=BATCH_SIZE=10
Environment=SLEEP_INTERVAL=5
Environment=NUM_WORKERS=2
Environment=THREADS_PER_WORKER=1
ExecStart=/usr/bin/python3 /opt/kima-hub/services/audio-analyzer/analyzer.py
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/systemd/system/kima-analyzer-clap.service
[Unit]
Description=Kima Hub CLAP Audio Analyzer
After=network.target postgresql.service redis-server.service kima-backend.service kima-analyzer.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/kima-hub/services/audio-analyzer-clap
Environment=DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
Environment=REDIS_URL=redis://localhost:6379
Environment=BACKEND_URL=http://localhost:3006
Environment=MUSIC_PATH=/music
Environment=SLEEP_INTERVAL=5
Environment=NUM_WORKERS=1
ExecStart=/usr/bin/python3 /opt/kima-hub/services/audio-analyzer-clap/analyzer.py
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now kima-backend kima-frontend kima-analyzer kima-analyzer-clap
msg_ok "Created Services"
motd_ssh
customize
cleanup_lxc

85
install/komodo-install.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Setup Docker Repository"
setup_deb822_repo \
"docker" \
"https://download.docker.com/linux/$(get_os_info id)/gpg" \
"https://download.docker.com/linux/$(get_os_info id)" \
"$(get_os_info codename)" \
"stable" \
"$(dpkg --print-architecture)"
msg_ok "Setup Docker Repository"
msg_info "Installing Docker"
$STD apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
msg_ok "Installed Docker"
echo "${TAB3}Choose the database for Komodo installation:"
echo "${TAB3}1) MongoDB (recommended)"
echo "${TAB3}2) FerretDB"
read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in
1)
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
2)
DB_COMPOSE_FILE="ferretdb.compose.yaml"
;;
*)
echo "Invalid choice. Defaulting to MongoDB."
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
esac
mkdir -p /opt/komodo
cd /opt/komodo
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/$DB_COMPOSE_FILE" -o "/opt/komodo/$DB_COMPOSE_FILE"
msg_info "Setup Komodo Environment"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env" -o "/opt/komodo/compose.env"
DB_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
ADMIN_PASSWORD=$(openssl rand -base64 8 | tr -d '/+=')
PASSKEY=$(openssl rand -base64 24 | tr -d '/+=')
WEBHOOK_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
JWT_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
sed -i "s/^KOMODO_DB_USERNAME=.*/KOMODO_DB_USERNAME=komodo_admin/" /opt/komodo/compose.env
sed -i "s/^KOMODO_DB_PASSWORD=.*/KOMODO_DB_PASSWORD=${DB_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_INIT_ADMIN_PASSWORD=changeme/KOMODO_INIT_ADMIN_PASSWORD=${ADMIN_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_PASSKEY=.*/KOMODO_PASSKEY=${PASSKEY}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_WEBHOOK_SECRET=.*/KOMODO_WEBHOOK_SECRET=${WEBHOOK_SECRET}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_JWT_SECRET=.*/KOMODO_JWT_SECRET=${JWT_SECRET}/" /opt/komodo/compose.env
{
echo "Komodo Credentials"
echo ""
echo "Admin User : admin"
echo "Admin Password: $ADMIN_PASSWORD"
} >>~/komodo.creds
msg_ok "Setup Komodo Environment"
msg_info "Initialize Komodo"
$STD docker compose -p komodo -f /opt/komodo/$DB_COMPOSE_FILE --env-file /opt/komodo/compose.env up -d
msg_ok "Initialized Komodo"
motd_ssh
customize
cleanup_lxc

View File

@@ -28,7 +28,7 @@ $STD apt install -y \
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv PYTHON_VERSION="3.12" setup_uv
PG_VERSION="16" setup_postgresql POSTGRES_VERSION="16" setup_postgresql
NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs
fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "latest" "/opt/mealie" fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "latest" "/opt/mealie"
PG_DB_NAME="mealie_db" PG_DB_USER="mealie_user" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db PG_DB_NAME="mealie_db" PG_DB_USER="mealie_user" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db

View File

@@ -51,7 +51,7 @@ while true; do
attempts=$((attempts + 1)) attempts=$((attempts + 1))
if [[ "$attempts" -ge 3 ]]; then if [[ "$attempts" -ge 3 ]]; then
msg_error "Maximum attempts reached. Exiting." msg_error "Maximum attempts reached. Exiting."
exit 254 exit 1
fi fi
done done
@@ -76,11 +76,11 @@ for i in {1..60}; do
elif [[ "$STATUS" == "unhealthy" ]]; then elif [[ "$STATUS" == "unhealthy" ]]; then
msg_error "NPMplus container is unhealthy! Check logs." msg_error "NPMplus container is unhealthy! Check logs."
docker logs "$CONTAINER_ID" docker logs "$CONTAINER_ID"
exit 150 exit 1
fi fi
fi fi
sleep 2 sleep 2
[[ $i -eq 60 ]] && msg_error "NPMplus container did not become healthy within 120s." && docker logs "$CONTAINER_ID" && exit 150 [[ $i -eq 60 ]] && msg_error "NPMplus container did not become healthy within 120s." && docker logs "$CONTAINER_ID" && exit 1
done done
msg_ok "Builded and started NPMplus" msg_ok "Builded and started NPMplus"

Some files were not shown because too many files have changed in this diff Show More