diff --git a/.github/DISCUSSION_TEMPLATE/request-script.yml b/.github/DISCUSSION_TEMPLATE/request-script.yml
index a2cf93136..64d694c97 100644
--- a/.github/DISCUSSION_TEMPLATE/request-script.yml
+++ b/.github/DISCUSSION_TEMPLATE/request-script.yml
@@ -12,17 +12,13 @@ body:
Requests may be closed if the application is out of scope, abandoned, too new, not publicly verifiable, or not suitable for a reliable Proxmox VE Helper-Scripts integration.
General requirements:
- - The application must be self-hosted.
- - The project must have an official public source repository.
- - The project must provide official releases, tags, or release tarballs.
- - The project must be actively maintained.
- - The official source repository must have at least 1,000 stars.
- - The latest official release or tag must not be older than 6 months.
- - The project itself must be at least 6 months old.
-
- Projects that do not meet these requirements may be closed without further evaluation.
-
- Exceptions to the 1,000-star requirement are rare and require a clearly verifiable, significant public adoption signal.
+ - The application should be self-hosted.
+ - The project should have an official public source repository.
+ - The project should provide official releases, tags, or release tarballs.
+ - The project should be actively maintained.
+ - The project should generally have at least 1,000 stars or a comparable public adoption signal.
+ - The latest official release or tag should not be older than 6 months.
+ - The project itself should be at least 6 months old.
- type: input
id: application-name
@@ -51,35 +47,6 @@ body:
validations:
required: true
- - type: markdown
- attributes:
- value: |
- ## ⚠️ Project Eligibility
-
- Before continuing, verify that the requested project meets the minimum requirements below.
-
- **Projects with fewer than 1,000 stars are generally not eligible for a script request.**
-
- Exceptions are only considered where there is a clearly verifiable, significant public adoption signal.
-
- - type: input
- id: repository-stars
- attributes:
- label: Repository Stars
- description: Enter the current number of stars of the official source repository.
- placeholder: "e.g., 15,000"
- validations:
- required: true
-
- - type: checkboxes
- id: minimum-stars
- attributes:
- label: Minimum Adoption Requirement
- description: Confirm that you have verified the project's public adoption.
- options:
- - label: The official source repository has at least 1,000 stars.
- required: true
-
- type: textarea
id: app-description
attributes:
diff --git a/.github/changelogs/2026/07.md b/.github/changelogs/2026/07.md
index 36a2207bc..4c20ca3e6 100644
--- a/.github/changelogs/2026/07.md
+++ b/.github/changelogs/2026/07.md
@@ -1,264 +1,3 @@
-## 2026-07-18
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - core: add configurable host CA inheritance during bootstrap [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15840](https://github.com/community-scripts/ProxmoxVE/pull/15840))
-
- - #### 🔧 Refactor
-
- - tools.func: Safe Delete Directorys & Update PYTHON_VERSION with setup_uv [@MickLesk](https://github.com/MickLesk) ([#15870](https://github.com/community-scripts/ProxmoxVE/pull/15870))
-
-### 🧰 Tools
-
- - #### ✨ New Features
-
- - [tools.update-lxcs] feat: optional reporting success/failures to heathchecks.io (or others) [@sir106](https://github.com/sir106) ([#15701](https://github.com/community-scripts/ProxmoxVE/pull/15701))
-
-## 2026-07-17
-
-### 🆕 New Scripts
-
- - Invidious ([#15824](https://github.com/community-scripts/ProxmoxVE/pull/15824))
-- OxiCloud ([#15823](https://github.com/community-scripts/ProxmoxVE/pull/15823))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - webtrees: initialize database schema before admin user creation [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15837](https://github.com/community-scripts/ProxmoxVE/pull/15837))
- - Fix DocuSeal missing Leptonica deps on install and update [@Copilot](https://github.com/Copilot) ([#15858](https://github.com/community-scripts/ProxmoxVE/pull/15858))
- - apache-guacamole: detect installed extensions during update [@TowyTowy](https://github.com/TowyTowy) ([#15841](https://github.com/community-scripts/ProxmoxVE/pull/15841))
- - CLIProxyAPI: fix update deleting config.yaml [@austinpilz](https://github.com/austinpilz) ([#15834](https://github.com/community-scripts/ProxmoxVE/pull/15834))
- - esphome: install libusb-1.0-0 for ESP-IDF native builds [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15838](https://github.com/community-scripts/ProxmoxVE/pull/15838))
-
- - #### ✨ New Features
-
- - AFFiNE: Bump to 0.27.0 [@MickLesk](https://github.com/MickLesk) ([#15848](https://github.com/community-scripts/ProxmoxVE/pull/15848))
- - n8n: unpin / use latest release [@MickLesk](https://github.com/MickLesk) ([#15817](https://github.com/community-scripts/ProxmoxVE/pull/15817))
- - Pin Opencloud to v7.3.0 [@vhsdream](https://github.com/vhsdream) ([#15826](https://github.com/community-scripts/ProxmoxVE/pull/15826))
-
- - #### 🔧 Refactor
-
- - SFTPGo: Update APT Repo & Re-Enable Script [@MickLesk](https://github.com/MickLesk) ([#15829](https://github.com/community-scripts/ProxmoxVE/pull/15829))
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - tools.func: enhance rbenv with profile updates / bundle in bashrc [@MickLesk](https://github.com/MickLesk) ([#15822](https://github.com/community-scripts/ProxmoxVE/pull/15822))
- - feat(build.func): notify users when already on a pinned script version [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15819](https://github.com/community-scripts/ProxmoxVE/pull/15819))
-
- - #### 💥 Breaking Changes
-
- - MongoDB: Implement kernel version check and patch [@MickLesk](https://github.com/MickLesk) ([#15821](https://github.com/community-scripts/ProxmoxVE/pull/15821))
-
-### 🧰 Tools
-
- - #### ✨ New Features
-
- - update-lxc: autoremove and autoclean after apt full-upgrade [@soupy-boy](https://github.com/soupy-boy) ([#15831](https://github.com/community-scripts/ProxmoxVE/pull/15831))
-
-## 2026-07-16
-
-### 🆕 New Scripts
-
- - Sync-In ([#15812](https://github.com/community-scripts/ProxmoxVE/pull/15812))
-- Beaverhabits ([#15813](https://github.com/community-scripts/ProxmoxVE/pull/15813))
-- Notediscovery ([#15811](https://github.com/community-scripts/ProxmoxVE/pull/15811))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Pin Immich to v3.0.3 [@vhsdream](https://github.com/vhsdream) ([#15790](https://github.com/community-scripts/ProxmoxVE/pull/15790))
-
-## 2026-07-15
-
-### 🆕 New Scripts
-
- - Nexterm ([#15688](https://github.com/community-scripts/ProxmoxVE/pull/15688))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - 2fauth: minor fixes for 8.0.0 [@MickLesk](https://github.com/MickLesk) ([#15795](https://github.com/community-scripts/ProxmoxVE/pull/15795))
- - SnapOtter: refactor update process to prebuild [@MickLesk](https://github.com/MickLesk) ([#15797](https://github.com/community-scripts/ProxmoxVE/pull/15797))
-
-### 💾 Core
-
- - #### 🔧 Refactor
-
- - tools.func: default Docker setup to official repo [@MickLesk](https://github.com/MickLesk) ([#15794](https://github.com/community-scripts/ProxmoxVE/pull/15794))
-
-## 2026-07-14
-
-### 🆕 New Scripts
-
- - Grav ([#15773](https://github.com/community-scripts/ProxmoxVE/pull/15773))
-- Yuvomi ([#15772](https://github.com/community-scripts/ProxmoxVE/pull/15772))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Lychee: Preserve uploads and ownership during update [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15768](https://github.com/community-scripts/ProxmoxVE/pull/15768))
- - Wanderer: Clean deploy and install plugins for v0.20.0 update [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15759](https://github.com/community-scripts/ProxmoxVE/pull/15759))
- - FileFlows: Handle update API 401, force update, and Node install [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15766](https://github.com/community-scripts/ProxmoxVE/pull/15766))
- - BirdNET-Go: Match new upstream release asset naming [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15758](https://github.com/community-scripts/ProxmoxVE/pull/15758))
- - [Upstream Fix] Immich: Fix loader priority [@vhsdream](https://github.com/vhsdream) ([#15755](https://github.com/community-scripts/ProxmoxVE/pull/15755))
-
- - #### ✨ New Features
-
- - Bump OpenCloud version to v7.2.2 [@MickLesk](https://github.com/MickLesk) ([#15769](https://github.com/community-scripts/ProxmoxVE/pull/15769))
- - Silverbullet: Add optional Runtime API install via Chromium [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15761](https://github.com/community-scripts/ProxmoxVE/pull/15761))
-
- - #### 💥 Breaking Changes
-
- - Pangolin: Bump to 1.20.0 | BREAKING: Switch to PostgreSQL [@MickLesk](https://github.com/MickLesk) ([#15682](https://github.com/community-scripts/ProxmoxVE/pull/15682))
-
- - #### 🔧 Refactor
-
- - AFFiNE: Pin to v0.26.3 [@MickLesk](https://github.com/MickLesk) ([#15782](https://github.com/community-scripts/ProxmoxVE/pull/15782))
-
-## 2026-07-13
-
-### 🆕 New Scripts
-
- - LeafWiki ([#15748](https://github.com/community-scripts/ProxmoxVE/pull/15748))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - fix(hyperion): keep service running after container reboot [@TowyTowy](https://github.com/TowyTowy) ([#15653](https://github.com/community-scripts/ProxmoxVE/pull/15653))
- - Change sign-in URL to admin URL in affine.sh [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15741](https://github.com/community-scripts/ProxmoxVE/pull/15741))
- - immich: use actual PostgreSQL version for VectorChord package lookup [@mnavon](https://github.com/mnavon) ([#15705](https://github.com/community-scripts/ProxmoxVE/pull/15705))
- - fix storyteller release selection for stable web tags [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15736](https://github.com/community-scripts/ProxmoxVE/pull/15736))
- - Docmost: Fix update procedure [@MickLesk](https://github.com/MickLesk) ([#15732](https://github.com/community-scripts/ProxmoxVE/pull/15732))
- - fix(shinobi): remove obsolete --unsafe-perm npm flag [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15730](https://github.com/community-scripts/ProxmoxVE/pull/15730))
-
- - #### 💥 Breaking Changes
-
- - reitti: update to v5 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15635](https://github.com/community-scripts/ProxmoxVE/pull/15635))
-
-### 💾 Core
-
- - #### 🐞 Bug Fixes
-
- - fix(build.func): parse script status without jq dependency [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15729](https://github.com/community-scripts/ProxmoxVE/pull/15729))
-
- - #### 🔧 Refactor
-
- - tools.func: some improvements (sql injection / command injection / guard) [@MickLesk](https://github.com/MickLesk) ([#15661](https://github.com/community-scripts/ProxmoxVE/pull/15661))
-
-## 2026-07-12
-
-### 🆕 New Scripts
-
- - AFFiNE ([#15690](https://github.com/community-scripts/ProxmoxVE/pull/15690))
-
-### 🚀 Updated Scripts
-
- - Immich: Bump version to 3.0.2 [@vhsdream](https://github.com/vhsdream) ([#15668](https://github.com/community-scripts/ProxmoxVE/pull/15668))
-
-### ❔ Uncategorized
-
- - fix(immich): correct Python indentation error in ct/immich.sh heredoc patch [@Copilot](https://github.com/Copilot) ([#15723](https://github.com/community-scripts/ProxmoxVE/pull/15723))
-
-## 2026-07-11
-
-### 🆕 New Scripts
-
- - LocalAGI ([#15687](https://github.com/community-scripts/ProxmoxVE/pull/15687))
-
-### 🚀 Updated Scripts
-
- - fix(adventurelog): allow pnpm build scripts so install/update doesn't abort [@TowyTowy](https://github.com/TowyTowy) ([#15681](https://github.com/community-scripts/ProxmoxVE/pull/15681))
-
- - #### 🐞 Bug Fixes
-
- - fix(fileflows): install .NET 10 ASP.NET Core Runtime to match current release [@TowyTowy](https://github.com/TowyTowy) ([#15702](https://github.com/community-scripts/ProxmoxVE/pull/15702))
- - Fix spacing on VLAN Input Box in haos-vm.sh [@pumrum](https://github.com/pumrum) ([#15696](https://github.com/community-scripts/ProxmoxVE/pull/15696))
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - [tools.func]: Add function to handle deployment via GitLab release tags [@tremor021](https://github.com/tremor021) ([#15641](https://github.com/community-scripts/ProxmoxVE/pull/15641))
-
-## 2026-07-10
-
-### 🆕 New Scripts
-
- - Squid ([#15605](https://github.com/community-scripts/ProxmoxVE/pull/15605))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Adapt to new artifact filename format for pocket id [@wollew](https://github.com/wollew) ([#15689](https://github.com/community-scripts/ProxmoxVE/pull/15689))
- - Fireshare: Fix for install and upgrade to v1.7.3 [@tremor021](https://github.com/tremor021) ([#15673](https://github.com/community-scripts/ProxmoxVE/pull/15673))
- - Endurain: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15674](https://github.com/community-scripts/ProxmoxVE/pull/15674))
-
-## 2026-07-09
-
-### 🚀 Updated Scripts
-
- - fix(pihole): repair Unbound DNS-over-TLS (DoT) forwarding config [@TowyTowy](https://github.com/TowyTowy) ([#15654](https://github.com/community-scripts/ProxmoxVE/pull/15654))
-
-## 2026-07-08
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Opencloud: Bump version to 7.2.1 [@vhsdream](https://github.com/vhsdream) ([#15655](https://github.com/community-scripts/ProxmoxVE/pull/15655))
- - BabyBuddy: Harden update script [@MickLesk](https://github.com/MickLesk) ([#15642](https://github.com/community-scripts/ProxmoxVE/pull/15642))
-
-## 2026-07-07
-
-### 🆕 New Scripts
-
- - Forgejo-Runner ([#15046](https://github.com/community-scripts/ProxmoxVE/pull/15046))
-
-## 2026-07-06
-
-### 🚀 Updated Scripts
-
- - Fix alignment in various ct end messages [@tremor021](https://github.com/tremor021) ([#15632](https://github.com/community-scripts/ProxmoxVE/pull/15632))
-- Immich: Update libvips to 8.18.4 [@vhsdream](https://github.com/vhsdream) ([#15619](https://github.com/community-scripts/ProxmoxVE/pull/15619))
-
- - #### 🐞 Bug Fixes
-
- - Wizarr: Build JS and CSS static assets [@vhsdream](https://github.com/vhsdream) ([#15634](https://github.com/community-scripts/ProxmoxVE/pull/15634))
- - RustDesk Server: Update URL format in rustdeskserver.sh [@tremor021](https://github.com/tremor021) ([#15626](https://github.com/community-scripts/ProxmoxVE/pull/15626))
- - attempt to port docker-vm to support arm64 [@asylumexp](https://github.com/asylumexp) ([#15611](https://github.com/community-scripts/ProxmoxVE/pull/15611))
- - fix(plane): don't clobber global app var, breaking /usr/bin/update [@asylumexp](https://github.com/asylumexp) ([#15612](https://github.com/community-scripts/ProxmoxVE/pull/15612))
-
- - #### 🔧 Refactor
-
- - cliproxyapi: point setup message at /management.html [@austinpilz](https://github.com/austinpilz) ([#15628](https://github.com/community-scripts/ProxmoxVE/pull/15628))
-
-### 🗑️ Deleted Scripts
-
- - Remove: FlowiseAI [@MickLesk](https://github.com/MickLesk) ([#15624](https://github.com/community-scripts/ProxmoxVE/pull/15624))
-
-## 2026-07-05
-
-### 🆕 New Scripts
-
- - excalidash ([#15604](https://github.com/community-scripts/ProxmoxVE/pull/15604))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - fix: homarr: cli [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15603](https://github.com/community-scripts/ProxmoxVE/pull/15603))
- - immich: vacuum smart_search/face_search before VectorChord bump [@irishpadres](https://github.com/irishpadres) ([#15607](https://github.com/community-scripts/ProxmoxVE/pull/15607))
-
## 2026-07-04
### 🚀 Updated Scripts
diff --git a/.github/workflows/close-invalid-pr-template.yml b/.github/workflows/close-invalid-pr-template.yml
deleted file mode 100644
index ce4c9a1bb..000000000
--- a/.github/workflows/close-invalid-pr-template.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-name: Close PRs Missing Template
-
-on:
- pull_request_target:
- branches: ["main"]
- types: [opened, edited, reopened, synchronize, labeled]
-
-jobs:
- validate-pr-template:
- if: github.repository == 'community-scripts/ProxmoxVE'
- runs-on: ubuntu-latest
- permissions:
- pull-requests: write
- issues: write
- contents: read
- steps:
- - name: Close PR if it does not follow the PR template
- uses: actions/github-script@v7
- with:
- script: |
- const pr = context.payload.pull_request;
- const prNumber = pr.number;
- const author = pr.user.login;
- const owner = context.repo.owner;
- const repo = context.repo.repo;
-
- const allowedBots = [
- "push-app-to-main[bot]",
- "push-app-to-main",
- "community-scripts-pr-app",
- "github-actions[bot]",
- "dependabot[bot]",
- ];
-
- if (allowedBots.includes(author) || author.endsWith("[bot]")) {
- core.info(`PR #${prNumber} by bot "${author}" — skipping template validation.`);
- return;
- }
-
- const association = pr.author_association;
- const exemptAssociations = ["OWNER", "MEMBER", "COLLABORATOR"];
- if (exemptAssociations.includes(association)) {
- core.info(`PR #${prNumber} by ${association} "${author}" — skipping template validation.`);
- return;
- }
-
- const labels = pr.labels.map((label) => label.name);
- const skipLabels = ["automated pr", "keep open"];
-
- if (skipLabels.some((label) => labels.includes(label))) {
- core.info(`PR #${prNumber} has a skip label (${labels.join(", ")}) — skipping template validation.`);
- return;
- }
-
- if (pr.draft) {
- core.info(`PR #${prNumber} is a draft — skipping template validation.`);
- return;
- }
-
- const body = pr.body || "";
- const failures = [];
-
- const requiredSections = [
- "## ✍️ Description",
- "## ✅ Prerequisites",
- "## 🛠️ Type of Change",
- ];
-
- for (const section of requiredSections) {
- if (!body.includes(section)) {
- failures.push(`Missing required section: \`${section}\``);
- }
- }
-
- const descriptionMatch = body.match(
- /## ✍️ Description\s*\n+([\s\S]*?)(?=\n## )/i
- );
- const description = (descriptionMatch?.[1] || "").trim();
- if (!description) {
- failures.push("The **Description** section is empty.");
- }
-
- const prerequisiteCheckboxes = [
- "**Self-review completed**",
- "**Tested thoroughly**",
- "**No security risks**",
- ];
-
- for (const checkbox of prerequisiteCheckboxes) {
- const escaped = checkbox.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
- const regex = new RegExp(`- \\[(x|X)\\]\\s*${escaped}`, "i");
- if (!regex.test(body)) {
- failures.push(`Prerequisite not checked: ${checkbox}`);
- }
- }
-
- const typeOfChangeCheckboxes = [
- "🐞 **Bug fix**",
- "✨ **New feature**",
- "💥 **Breaking change**",
- "🆕 **New script**",
- "🌍 **Website update**",
- "🔧 **Refactoring / Code Cleanup**",
- "📝 **Documentation update**",
- ];
-
- const hasTypeChecked = typeOfChangeCheckboxes.some((checkbox) => {
- const escaped = checkbox.replace(/([.*+?^=!:${}()|[\]\/\\])/g, "\\$1");
- const regex = new RegExp(`- \\[(x|X)\\]\\s*${escaped}`, "i");
- return regex.test(body);
- });
-
- if (!hasTypeChecked) {
- failures.push("At least one **Type of Change** checkbox must be checked.");
- }
-
- if (failures.length === 0) {
- core.info(`PR #${prNumber} follows the PR template.`);
- return;
- }
-
- core.info(`Closing PR #${prNumber} — template validation failed.`);
-
- const templateUrl =
- "https://github.com/community-scripts/ProxmoxVE/blob/main/.github/pull_request_template.md";
- const failureList = failures.map((item) => `- ${item}`).join("\n");
-
- const comment = [
- `👋 Hi @${author},`,
- ``,
- `This pull request was closed because it does not follow the [PR template](${templateUrl}).`,
- ``,
- `Please fix the following and open a new PR (or reopen this one after updating the description):`,
- ``,
- failureList,
- ``,
- `> Use the template sections, fill in the description, check all prerequisite boxes, and select at least one type of change.`,
- ``,
- `Maintainers can add the \`keep open\` label to exempt a PR from this check.`,
- ``,
- `Thank you for contributing! 🙏`,
- ].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",
- });
-
- await github.rest.issues.addLabels({
- owner,
- repo,
- issue_number: prNumber,
- labels: ["missing pr template"],
- });
diff --git a/.github/workflows/delete-merged-branches.yml b/.github/workflows/delete-merged-branches.yml
index 09a9f8ab1..aafaf2b44 100644
--- a/.github/workflows/delete-merged-branches.yml
+++ b/.github/workflows/delete-merged-branches.yml
@@ -91,30 +91,6 @@ jobs:
let skipped = 0;
for (const branch of candidates) {
- // A branch name can be reused after an earlier PR was merged. Never delete a
- // branch while it is the head of a current open PR, even if it is also a
- // candidate from an older merged PR.
- try {
- const { data: openPrs } = await github.rest.pulls.list({
- owner,
- repo,
- state: "open",
- head: `${owner}:${branch}`,
- per_page: 1,
- });
-
- if (openPrs.length > 0) {
- console.log(`Skipped "${branch}" (head of open PR #${openPrs[0].number})`);
- skipped++;
- continue;
- }
- } catch (error) {
- // Do not risk deleting a branch if GitHub cannot confirm it has no open PR.
- console.log(`Failed to check open PRs for "${branch}": ${error.message}`);
- skipped++;
- continue;
- }
-
// Confirm the branch still exists and isn't protected.
let branchData;
try {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99aa845ce..2dabf3bbe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -71,12 +71,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
-
-
-
-
-
-
@@ -93,7 +87,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
-July (18 entries)
+July (4 entries)
[View July 2026 Changelog](.github/changelogs/2026/07.md)
@@ -505,245 +499,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
-## 2026-07-19
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - change trek repo to liketrek/TREK [@asylumexp](https://github.com/asylumexp) ([#15893](https://github.com/community-scripts/ProxmoxVE/pull/15893))
- - update authentik to 2026.5.5 [@thieneret](https://github.com/thieneret) ([#15855](https://github.com/community-scripts/ProxmoxVE/pull/15855))
- - [FIX] BookOrbit: add missing `restore_backup` during update [@vhsdream](https://github.com/vhsdream) ([#15881](https://github.com/community-scripts/ProxmoxVE/pull/15881))
-
- - #### ✨ New Features
-
- - tools.func: centralize deploy tail + trap-based tmpdir cleanup [@MickLesk](https://github.com/MickLesk) ([#15872](https://github.com/community-scripts/ProxmoxVE/pull/15872))
- - Update OPNsense from 26.1 to 26.7 [@tdn131](https://github.com/tdn131) ([#15895](https://github.com/community-scripts/ProxmoxVE/pull/15895))
-
-### 💾 Core
-
- - Revert "core: add configurable host CA inheritance during bootstrap" [@MickLesk](https://github.com/MickLesk) ([#15886](https://github.com/community-scripts/ProxmoxVE/pull/15886))
-
-## 2026-07-18
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - core: add configurable host CA inheritance during bootstrap [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15840](https://github.com/community-scripts/ProxmoxVE/pull/15840))
-
- - #### 🔧 Refactor
-
- - tools.func: Safe Delete Directorys & Update PYTHON_VERSION with setup_uv [@MickLesk](https://github.com/MickLesk) ([#15870](https://github.com/community-scripts/ProxmoxVE/pull/15870))
-
-### 🧰 Tools
-
- - #### ✨ New Features
-
- - [tools.update-lxcs] feat: optional reporting success/failures to heathchecks.io (or others) [@sir106](https://github.com/sir106) ([#15701](https://github.com/community-scripts/ProxmoxVE/pull/15701))
-
-## 2026-07-17
-
-### 🆕 New Scripts
-
- - Invidious ([#15824](https://github.com/community-scripts/ProxmoxVE/pull/15824))
-- OxiCloud ([#15823](https://github.com/community-scripts/ProxmoxVE/pull/15823))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - webtrees: initialize database schema before admin user creation [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15837](https://github.com/community-scripts/ProxmoxVE/pull/15837))
- - Fix DocuSeal missing Leptonica deps on install and update [@Copilot](https://github.com/Copilot) ([#15858](https://github.com/community-scripts/ProxmoxVE/pull/15858))
- - apache-guacamole: detect installed extensions during update [@TowyTowy](https://github.com/TowyTowy) ([#15841](https://github.com/community-scripts/ProxmoxVE/pull/15841))
- - CLIProxyAPI: fix update deleting config.yaml [@austinpilz](https://github.com/austinpilz) ([#15834](https://github.com/community-scripts/ProxmoxVE/pull/15834))
- - esphome: install libusb-1.0-0 for ESP-IDF native builds [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15838](https://github.com/community-scripts/ProxmoxVE/pull/15838))
-
- - #### ✨ New Features
-
- - AFFiNE: Bump to 0.27.0 [@MickLesk](https://github.com/MickLesk) ([#15848](https://github.com/community-scripts/ProxmoxVE/pull/15848))
- - n8n: unpin / use latest release [@MickLesk](https://github.com/MickLesk) ([#15817](https://github.com/community-scripts/ProxmoxVE/pull/15817))
- - Pin Opencloud to v7.3.0 [@vhsdream](https://github.com/vhsdream) ([#15826](https://github.com/community-scripts/ProxmoxVE/pull/15826))
-
- - #### 🔧 Refactor
-
- - SFTPGo: Update APT Repo & Re-Enable Script [@MickLesk](https://github.com/MickLesk) ([#15829](https://github.com/community-scripts/ProxmoxVE/pull/15829))
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - tools.func: enhance rbenv with profile updates / bundle in bashrc [@MickLesk](https://github.com/MickLesk) ([#15822](https://github.com/community-scripts/ProxmoxVE/pull/15822))
- - feat(build.func): notify users when already on a pinned script version [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15819](https://github.com/community-scripts/ProxmoxVE/pull/15819))
-
- - #### 💥 Breaking Changes
-
- - MongoDB: Implement kernel version check and patch [@MickLesk](https://github.com/MickLesk) ([#15821](https://github.com/community-scripts/ProxmoxVE/pull/15821))
-
-### 🧰 Tools
-
- - #### ✨ New Features
-
- - update-lxc: autoremove and autoclean after apt full-upgrade [@soupy-boy](https://github.com/soupy-boy) ([#15831](https://github.com/community-scripts/ProxmoxVE/pull/15831))
-
-## 2026-07-16
-
-### 🆕 New Scripts
-
- - Sync-In ([#15812](https://github.com/community-scripts/ProxmoxVE/pull/15812))
-- Beaverhabits ([#15813](https://github.com/community-scripts/ProxmoxVE/pull/15813))
-- Notediscovery ([#15811](https://github.com/community-scripts/ProxmoxVE/pull/15811))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Pin Immich to v3.0.3 [@vhsdream](https://github.com/vhsdream) ([#15790](https://github.com/community-scripts/ProxmoxVE/pull/15790))
-
-## 2026-07-15
-
-### 🆕 New Scripts
-
- - Nexterm ([#15688](https://github.com/community-scripts/ProxmoxVE/pull/15688))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - 2fauth: minor fixes for 8.0.0 [@MickLesk](https://github.com/MickLesk) ([#15795](https://github.com/community-scripts/ProxmoxVE/pull/15795))
- - SnapOtter: refactor update process to prebuild [@MickLesk](https://github.com/MickLesk) ([#15797](https://github.com/community-scripts/ProxmoxVE/pull/15797))
-
-### 💾 Core
-
- - #### 🔧 Refactor
-
- - tools.func: default Docker setup to official repo [@MickLesk](https://github.com/MickLesk) ([#15794](https://github.com/community-scripts/ProxmoxVE/pull/15794))
-
-## 2026-07-14
-
-### 🆕 New Scripts
-
- - Grav ([#15773](https://github.com/community-scripts/ProxmoxVE/pull/15773))
-- Yuvomi ([#15772](https://github.com/community-scripts/ProxmoxVE/pull/15772))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Lychee: Preserve uploads and ownership during update [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15768](https://github.com/community-scripts/ProxmoxVE/pull/15768))
- - Wanderer: Clean deploy and install plugins for v0.20.0 update [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15759](https://github.com/community-scripts/ProxmoxVE/pull/15759))
- - FileFlows: Handle update API 401, force update, and Node install [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15766](https://github.com/community-scripts/ProxmoxVE/pull/15766))
- - BirdNET-Go: Match new upstream release asset naming [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15758](https://github.com/community-scripts/ProxmoxVE/pull/15758))
- - [Upstream Fix] Immich: Fix loader priority [@vhsdream](https://github.com/vhsdream) ([#15755](https://github.com/community-scripts/ProxmoxVE/pull/15755))
-
- - #### ✨ New Features
-
- - Bump OpenCloud version to v7.2.2 [@MickLesk](https://github.com/MickLesk) ([#15769](https://github.com/community-scripts/ProxmoxVE/pull/15769))
- - Silverbullet: Add optional Runtime API install via Chromium [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15761](https://github.com/community-scripts/ProxmoxVE/pull/15761))
-
- - #### 💥 Breaking Changes
-
- - Pangolin: Bump to 1.20.0 | BREAKING: Switch to PostgreSQL [@MickLesk](https://github.com/MickLesk) ([#15682](https://github.com/community-scripts/ProxmoxVE/pull/15682))
-
- - #### 🔧 Refactor
-
- - AFFiNE: Pin to v0.26.3 [@MickLesk](https://github.com/MickLesk) ([#15782](https://github.com/community-scripts/ProxmoxVE/pull/15782))
-
-## 2026-07-13
-
-### 🆕 New Scripts
-
- - LeafWiki ([#15748](https://github.com/community-scripts/ProxmoxVE/pull/15748))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - fix(hyperion): keep service running after container reboot [@TowyTowy](https://github.com/TowyTowy) ([#15653](https://github.com/community-scripts/ProxmoxVE/pull/15653))
- - Change sign-in URL to admin URL in affine.sh [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15741](https://github.com/community-scripts/ProxmoxVE/pull/15741))
- - immich: use actual PostgreSQL version for VectorChord package lookup [@mnavon](https://github.com/mnavon) ([#15705](https://github.com/community-scripts/ProxmoxVE/pull/15705))
- - fix storyteller release selection for stable web tags [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15736](https://github.com/community-scripts/ProxmoxVE/pull/15736))
- - Docmost: Fix update procedure [@MickLesk](https://github.com/MickLesk) ([#15732](https://github.com/community-scripts/ProxmoxVE/pull/15732))
- - fix(shinobi): remove obsolete --unsafe-perm npm flag [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15730](https://github.com/community-scripts/ProxmoxVE/pull/15730))
-
- - #### 💥 Breaking Changes
-
- - reitti: update to v5 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15635](https://github.com/community-scripts/ProxmoxVE/pull/15635))
-
-### 💾 Core
-
- - #### 🐞 Bug Fixes
-
- - fix(build.func): parse script status without jq dependency [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15729](https://github.com/community-scripts/ProxmoxVE/pull/15729))
-
- - #### 🔧 Refactor
-
- - tools.func: some improvements (sql injection / command injection / guard) [@MickLesk](https://github.com/MickLesk) ([#15661](https://github.com/community-scripts/ProxmoxVE/pull/15661))
-
-## 2026-07-12
-
-### 🆕 New Scripts
-
- - AFFiNE ([#15690](https://github.com/community-scripts/ProxmoxVE/pull/15690))
-
-### 🚀 Updated Scripts
-
- - Immich: Bump version to 3.0.2 [@vhsdream](https://github.com/vhsdream) ([#15668](https://github.com/community-scripts/ProxmoxVE/pull/15668))
-
-### ❔ Uncategorized
-
- - fix(immich): correct Python indentation error in ct/immich.sh heredoc patch [@Copilot](https://github.com/Copilot) ([#15723](https://github.com/community-scripts/ProxmoxVE/pull/15723))
-
-## 2026-07-11
-
-### 🆕 New Scripts
-
- - LocalAGI ([#15687](https://github.com/community-scripts/ProxmoxVE/pull/15687))
-
-### 🚀 Updated Scripts
-
- - fix(adventurelog): allow pnpm build scripts so install/update doesn't abort [@TowyTowy](https://github.com/TowyTowy) ([#15681](https://github.com/community-scripts/ProxmoxVE/pull/15681))
-
- - #### 🐞 Bug Fixes
-
- - fix(fileflows): install .NET 10 ASP.NET Core Runtime to match current release [@TowyTowy](https://github.com/TowyTowy) ([#15702](https://github.com/community-scripts/ProxmoxVE/pull/15702))
- - Fix spacing on VLAN Input Box in haos-vm.sh [@pumrum](https://github.com/pumrum) ([#15696](https://github.com/community-scripts/ProxmoxVE/pull/15696))
-
-### 💾 Core
-
- - #### ✨ New Features
-
- - [tools.func]: Add function to handle deployment via GitLab release tags [@tremor021](https://github.com/tremor021) ([#15641](https://github.com/community-scripts/ProxmoxVE/pull/15641))
-
-## 2026-07-10
-
-### 🆕 New Scripts
-
- - Squid ([#15605](https://github.com/community-scripts/ProxmoxVE/pull/15605))
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Adapt to new artifact filename format for pocket id [@wollew](https://github.com/wollew) ([#15689](https://github.com/community-scripts/ProxmoxVE/pull/15689))
- - Fireshare: Fix for install and upgrade to v1.7.3 [@tremor021](https://github.com/tremor021) ([#15673](https://github.com/community-scripts/ProxmoxVE/pull/15673))
- - Endurain: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15674](https://github.com/community-scripts/ProxmoxVE/pull/15674))
-
-## 2026-07-09
-
-### 🚀 Updated Scripts
-
- - fix(pihole): repair Unbound DNS-over-TLS (DoT) forwarding config [@TowyTowy](https://github.com/TowyTowy) ([#15654](https://github.com/community-scripts/ProxmoxVE/pull/15654))
-
-## 2026-07-08
-
-### 🚀 Updated Scripts
-
- - #### 🐞 Bug Fixes
-
- - Opencloud: Bump version to 7.2.1 [@vhsdream](https://github.com/vhsdream) ([#15655](https://github.com/community-scripts/ProxmoxVE/pull/15655))
- - BabyBuddy: Harden update script [@MickLesk](https://github.com/MickLesk) ([#15642](https://github.com/community-scripts/ProxmoxVE/pull/15642))
-
## 2026-07-07
### 🆕 New Scripts
@@ -1175,4 +930,259 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- chore(ct): sync coredns defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#15182](https://github.com/community-scripts/ProxmoxVE/pull/15182))
- chore(ct): sync gatus defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#15184](https://github.com/community-scripts/ProxmoxVE/pull/15184))
-- chore(ct): sync bitmagnet defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#15183](https://github.com/community-scripts/ProxmoxVE/pull/15183))
\ No newline at end of file
+- chore(ct): sync bitmagnet defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#15183](https://github.com/community-scripts/ProxmoxVE/pull/15183))
+
+## 2026-06-18
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - flowise: add deps / uv / python 3.11 [@MickLesk](https://github.com/MickLesk) ([#15177](https://github.com/community-scripts/ProxmoxVE/pull/15177))
+
+ - #### 💥 Breaking Changes
+
+ - refactor: crafty-controller [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15178](https://github.com/community-scripts/ProxmoxVE/pull/15178))
+
+## 2026-06-17
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - kasm: fix release detection [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15151](https://github.com/community-scripts/ProxmoxVE/pull/15151))
+
+ - #### ✨ New Features
+
+ - trek: update install and upgrade workflow for v3.1.0 [@MickLesk](https://github.com/MickLesk) ([#15165](https://github.com/community-scripts/ProxmoxVE/pull/15165))
+
+ - #### 💥 Breaking Changes
+
+ - TREK: Pin version [@tremor021](https://github.com/tremor021) ([#15156](https://github.com/community-scripts/ProxmoxVE/pull/15156))
+
+ - #### 🔧 Refactor
+
+ - chore(paperless-ngx): pin version to prevent v3 update [@tomfrenzel](https://github.com/tomfrenzel) ([#15171](https://github.com/community-scripts/ProxmoxVE/pull/15171))
+
+### 🧰 Tools
+
+ - #### 🐞 Bug Fixes
+
+ - immich public proxy: replace npm install with npm ci for consistent dependency installation [@MickLesk](https://github.com/MickLesk) ([#15166](https://github.com/community-scripts/ProxmoxVE/pull/15166))
+
+## 2026-06-16
+
+### 🆕 New Scripts
+
+ - Feishin ([#15130](https://github.com/community-scripts/ProxmoxVE/pull/15130))
+- Kiwix ([#15131](https://github.com/community-scripts/ProxmoxVE/pull/15131))
+- Add runtime status guard and deleted script stubs [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15125](https://github.com/community-scripts/ProxmoxVE/pull/15125))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - fix(degoog): use localhost for valkey url [@ethan-hgwr](https://github.com/ethan-hgwr) ([#15149](https://github.com/community-scripts/ProxmoxVE/pull/15149))
+ - Fix InvoiceShelf install/update Yarn package manager mismatch [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15141](https://github.com/community-scripts/ProxmoxVE/pull/15141))
+ - fix storyteller install failure with yarn 4 corepack [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15140](https://github.com/community-scripts/ProxmoxVE/pull/15140))
+ - fix: generate policy-compliant OpenObserve root password [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15137](https://github.com/community-scripts/ProxmoxVE/pull/15137))
+
+## 2026-06-15
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Watcharr: Clean install on update [@tremor021](https://github.com/tremor021) ([#15119](https://github.com/community-scripts/ProxmoxVE/pull/15119))
+ - Vaultwarden: extend version check for VaultWarden update [@MickLesk](https://github.com/MickLesk) ([#15105](https://github.com/community-scripts/ProxmoxVE/pull/15105))
+
+ - #### ✨ New Features
+
+ - degoog: add curl-impersonate to script [@MickLesk](https://github.com/MickLesk) ([#15117](https://github.com/community-scripts/ProxmoxVE/pull/15117))
+
+### 💾 Core
+
+ - #### ✨ New Features
+
+ - tools.func: extend mesa-vulkan-drivers and vulkan-tools to installation for ARC GPU's [@MickLesk](https://github.com/MickLesk) ([#15106](https://github.com/community-scripts/ProxmoxVE/pull/15106))
+
+ - #### 🔧 Refactor
+
+ - core: improve mirror selection and error handling [@MickLesk](https://github.com/MickLesk) ([#15108](https://github.com/community-scripts/ProxmoxVE/pull/15108))
+ - core: implement gateway validation for DHCP and static networks [@MickLesk](https://github.com/MickLesk) ([#15107](https://github.com/community-scripts/ProxmoxVE/pull/15107))
+
+## 2026-06-14
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Iinvoiceninja: fix nginx setup assets port [@MickLesk](https://github.com/MickLesk) ([#15090](https://github.com/community-scripts/ProxmoxVE/pull/15090))
+ - CheckMK: remove stale backup site before creating new backup during update [@MickLesk](https://github.com/MickLesk) ([#15088](https://github.com/community-scripts/ProxmoxVE/pull/15088))
+
+ - #### 🔧 Refactor
+
+ - Refactor: Implement backup functions for scripts C-D [@tremor021](https://github.com/tremor021) ([#15096](https://github.com/community-scripts/ProxmoxVE/pull/15096))
+
+## 2026-06-13
+
+### 🆕 New Scripts
+
+ - BookOrbit ([#15080](https://github.com/community-scripts/ProxmoxVE/pull/15080))
+
+### 🚀 Updated Scripts
+
+ - Update authentik version to 2026.5.3 [@thieneret](https://github.com/thieneret) ([#15093](https://github.com/community-scripts/ProxmoxVE/pull/15093))
+
+ - #### 🐞 Bug Fixes
+
+ - Immich: Update image-processing libraries [@vhsdream](https://github.com/vhsdream) ([#15082](https://github.com/community-scripts/ProxmoxVE/pull/15082))
+ - HomeBox: Support v0.26.0 [@tomfrenzel](https://github.com/tomfrenzel) ([#15086](https://github.com/community-scripts/ProxmoxVE/pull/15086))
+
+ - #### 🔧 Refactor
+
+ - Refactor: Implement backup functions for scripts A-B [@tremor021](https://github.com/tremor021) ([#15075](https://github.com/community-scripts/ProxmoxVE/pull/15075))
+
+## 2026-06-12
+
+### 🆕 New Scripts
+
+ - Twenty ([#15047](https://github.com/community-scripts/ProxmoxVE/pull/15047))
+- Alpine-Cinny ([#15044](https://github.com/community-scripts/ProxmoxVE/pull/15044))
+
+### 💾 Core
+
+ - #### ✨ New Features
+
+ - [core] Implement backup and restore functions [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15067](https://github.com/community-scripts/ProxmoxVE/pull/15067))
+
+## 2026-06-11
+
+### 🆕 New Scripts
+
+ - Clickhouse ([#15045](https://github.com/community-scripts/ProxmoxVE/pull/15045))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Manyfold: add new dependency [@MickLesk](https://github.com/MickLesk) ([#15040](https://github.com/community-scripts/ProxmoxVE/pull/15040))
+ - OpenArchiver: switch Rebuild Function [@MickLesk](https://github.com/MickLesk) ([#15042](https://github.com/community-scripts/ProxmoxVE/pull/15042))
+ - CLIProxyAPI: Save management password to creds file [@tremor021](https://github.com/tremor021) ([#15051](https://github.com/community-scripts/ProxmoxVE/pull/15051))
+ - Jotty: Fix wrong path test in config restore [@vhsdream](https://github.com/vhsdream) ([#15038](https://github.com/community-scripts/ProxmoxVE/pull/15038))
+ - Fix for cross-seed after node upgrade [@TorinFrancis](https://github.com/TorinFrancis) ([#15025](https://github.com/community-scripts/ProxmoxVE/pull/15025))
+
+ - #### 🔧 Refactor
+
+ - Alpine-Nextcloud: Upgrade PHP and dependencies in installation script [@MickLesk](https://github.com/MickLesk) ([#15039](https://github.com/community-scripts/ProxmoxVE/pull/15039))
+ - [arm64] porting stage 1: set script arm64 statuses to yes [@asylumexp](https://github.com/asylumexp) ([#15052](https://github.com/community-scripts/ProxmoxVE/pull/15052))
+
+### 💾 Core
+
+ - #### ✨ New Features
+
+ - misc scripts: add support for arm64 [@asylumexp](https://github.com/asylumexp) ([#12639](https://github.com/community-scripts/ProxmoxVE/pull/12639))
+
+ - #### 🔧 Refactor
+
+ - [arm64] remove logic for custom debian arm64 template [@asylumexp](https://github.com/asylumexp) ([#15050](https://github.com/community-scripts/ProxmoxVE/pull/15050))
+
+### 📚 Documentation
+
+ - (github): Revise script request template [@MickLesk](https://github.com/MickLesk) ([#15058](https://github.com/community-scripts/ProxmoxVE/pull/15058))
+
+## 2026-06-10
+
+### 🆕 New Scripts
+
+ - Baserow ([#14968](https://github.com/community-scripts/ProxmoxVE/pull/14968))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Koillection: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15033](https://github.com/community-scripts/ProxmoxVE/pull/15033))
+
+## 2026-06-09
+
+### 🆕 New Scripts
+
+ - paperclip ([#14990](https://github.com/community-scripts/ProxmoxVE/pull/14990))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - endurain: Install pytz package during backend setup [@MickLesk](https://github.com/MickLesk) ([#15014](https://github.com/community-scripts/ProxmoxVE/pull/15014))
+
+ - #### 🔧 Refactor
+
+ - Refactor: Proxmox Backup Server - use deb822 [@MickLesk](https://github.com/MickLesk) ([#15013](https://github.com/community-scripts/ProxmoxVE/pull/15013))
+
+## 2026-06-08
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - security: Fix HTTP to HTTPS for all package and repository downloads [@MickLesk](https://github.com/MickLesk) ([#15009](https://github.com/community-scripts/ProxmoxVE/pull/15009))
+ - homelable: preserve MCP server config across updates [@ferr079](https://github.com/ferr079) ([#14996](https://github.com/community-scripts/ProxmoxVE/pull/14996))
+ - changedetection: migrate Python install to uv venv [@ferr079](https://github.com/ferr079) ([#14995](https://github.com/community-scripts/ProxmoxVE/pull/14995))
+
+ - #### 🔧 Refactor
+
+ - Update Flowwiseai to node 24 [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14999](https://github.com/community-scripts/ProxmoxVE/pull/14999))
+
+### 🧰 Tools
+
+ - #### 🐞 Bug Fixes
+
+ - security: Fix MITM RCE vulnerability in microcode scripts (CVE) [@MickLesk](https://github.com/MickLesk) ([#15007](https://github.com/community-scripts/ProxmoxVE/pull/15007))
+
+## 2026-06-07
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Immich: use actual installed PostgreSQL version for vchord package [@MickLesk](https://github.com/MickLesk) ([#14989](https://github.com/community-scripts/ProxmoxVE/pull/14989))
+
+ - #### 🔧 Refactor
+
+ - Navidrome: remove genereic filebrowser addon setup [@MickLesk](https://github.com/MickLesk) ([#14991](https://github.com/community-scripts/ProxmoxVE/pull/14991))
+
+## 2026-06-06
+
+### 🆕 New Scripts
+
+ - Spliit ([#14966](https://github.com/community-scripts/ProxmoxVE/pull/14966))
+- Tolgee ([#14965](https://github.com/community-scripts/ProxmoxVE/pull/14965))
+- XYOps ([#14967](https://github.com/community-scripts/ProxmoxVE/pull/14967))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Photoprism: Allow env variables with spaces [@Badintral](https://github.com/Badintral) ([#14969](https://github.com/community-scripts/ProxmoxVE/pull/14969))
+
+## 2026-06-05
+
+### 🆕 New Scripts
+
+ - MatterJS-Server ([#14951](https://github.com/community-scripts/ProxmoxVE/pull/14951))
+- CyberChef ([#14952](https://github.com/community-scripts/ProxmoxVE/pull/14952))
+
+### 🚀 Updated Scripts
+
+ - #### 🐞 Bug Fixes
+
+ - Jackett: Create missing .env file [@tremor021](https://github.com/tremor021) ([#14959](https://github.com/community-scripts/ProxmoxVE/pull/14959))
+ - OpenThread-BR: use systemd instead of init.d [@tomfrenzel](https://github.com/tomfrenzel) ([#14942](https://github.com/community-scripts/ProxmoxVE/pull/14942))
+
+ - #### ✨ New Features
+
+ - AMD IGPU support [@Learath](https://github.com/Learath) ([#14944](https://github.com/community-scripts/ProxmoxVE/pull/14944))
+
+ - #### 💥 Breaking Changes
+
+ - update authentik to 2026.5.2 [@thieneret](https://github.com/thieneret) ([#14846](https://github.com/community-scripts/ProxmoxVE/pull/14846))
\ No newline at end of file
diff --git a/ct/2fauth.sh b/ct/2fauth.sh
index 5b5dc3eb7..506f140d8 100644
--- a/ct/2fauth.sh
+++ b/ct/2fauth.sh
@@ -60,7 +60,6 @@ function update_script() {
php artisan 2fauth:install
chown -R www-data: /opt/2fauth
chmod -R 755 /opt/2fauth
- $STD php artisan 2fauth:fix-passport-key-permissions
$STD systemctl restart php8.4-fpm
$STD systemctl restart nginx
msg_ok "Configured 2FAuth"
diff --git a/ct/adventurelog.sh b/ct/adventurelog.sh
index 98327747e..0da4c09c0 100644
--- a/ct/adventurelog.sh
+++ b/ct/adventurelog.sh
@@ -60,7 +60,6 @@ function update_script() {
$STD .venv/bin/python -m manage migrate
cd /opt/adventurelog/frontend
- grep -q "^dangerouslyAllowAllBuilds:" ./pnpm-workspace.yaml 2>/dev/null || echo "dangerouslyAllowAllBuilds: true" >>./pnpm-workspace.yaml
$STD pnpm i
$STD pnpm build
msg_ok "Updated AdventureLog"
diff --git a/ct/affine.sh b/ct/affine.sh
deleted file mode 100644
index 1480c2a99..000000000
--- a/ct/affine.sh
+++ /dev/null
@@ -1,131 +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/toeverything/AFFiNE
-
-APP="AFFiNE"
-var_tags="${var_tags:-knowledge;notes;workspace}"
-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_arm64="${var_arm64:-no}"
-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/affine ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- RELEASE="v0.27.0"
- if check_for_gh_release "affine_app" "toeverything/AFFiNE" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
- msg_info "Stopping Services"
- systemctl stop affine-web affine-worker
- msg_ok "Stopped Services"
-
- ensure_dependencies cmake
-
- create_backup /root/.affine/config /root/.affine/storage
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "affine_app" "toeverything/AFFiNE" "tarball" "${RELEASE}" "/opt/affine"
-
- msg_info "Rebuilding Application (Patience ~25 mins, don't close the console!)"
- cd /opt/affine
- source /root/.profile
- export PATH="/root/.cargo/bin:/root/.rbenv/shims:$PATH"
-
- set -a && source /opt/affine/.env && set +a
-
- export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
- export VITE_CORE_COMMIT_SHA=$(cat ~/.affine_app)
-
- # Initialize git repo (required for build process)
- export HUSKY=0
- $STD git init -q
- $STD git config user.email "build@local"
- $STD git config user.name "Build"
- $STD git add -A
- $STD git commit -q -m "update" --no-verify --allow-empty
-
- # Force Turbo to run sequentially
- mkdir -p /opt/affine/.turbo
- cat </opt/affine/.turbo/config.json
-{
- "concurrency": 1
-}
-TURBO
-
- $STD corepack enable
- $STD corepack prepare yarn@4.13.0 --activate
- $STD yarn config set enableTelemetry 0
-
- export NODE_OPTIONS="--max-old-space-size=2048"
- $STD yarn install
- $STD npm install -g typescript
-
- $STD yarn affine @affine/native build
- $STD yarn affine @affine/server-native build
-
- # Create architecture-specific symlinks
- ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.x64.node
- ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.arm64.node
- ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.armv7.node
-
- $STD yarn affine init
- $STD yarn affine build -p @affine/reader
- $STD yarn affine build -p @affine/server
-
- export NODE_OPTIONS="--max-old-space-size=4096"
- $STD yarn affine build -p @affine/web
- $STD yarn affine build -p @affine/admin
-
- # Copy web assets
- mkdir -p /opt/affine/packages/backend/server/static
- cp -r /opt/affine/packages/frontend/apps/web/dist/* /opt/affine/packages/backend/server/static/
- mkdir -p /opt/affine/packages/backend/server/static/admin
- cp -r /opt/affine/packages/frontend/admin/dist/* /opt/affine/packages/backend/server/static/admin/
-
- # Mobile manifest placeholder
- mkdir -p /opt/affine/packages/backend/server/static/mobile
- echo '{"publicPath":"/","js":[],"css":[],"gitHash":"","description":""}' \
- >/opt/affine/packages/backend/server/static/mobile/assets-manifest.json
-
- # Run migrations
- cd /opt/affine/packages/backend/server
- set -a && source /opt/affine/.env && set +a
- $STD node ./scripts/self-host-predeploy.js
-
- restore_backup
-
- msg_info "Starting Services"
- systemctl start affine-web affine-worker
- 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 "${GATEWAY}${BGN}http://${IP}:3010/admin${CL}"
diff --git a/ct/apache-guacamole.sh b/ct/apache-guacamole.sh
index 89f1b973b..bbd9673cc 100644
--- a/ct/apache-guacamole.sh
+++ b/ct/apache-guacamole.sh
@@ -146,7 +146,7 @@ function update_script() {
# Check and upgrade optional extensions
# TOTP Extension
- if compgen -G "/etc/guacamole/extensions/guacamole-auth-totp-*.jar" >/dev/null; then
+ if [[ -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar ]]; then
msg_info "Updating TOTP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar
curl_download "/tmp/guacamole-auth-totp.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-totp-${LATEST_SERVER}.tar.gz"
@@ -158,7 +158,7 @@ function update_script() {
fi
# DUO Extension
- if compgen -G "/etc/guacamole/extensions/guacamole-auth-duo-*.jar" >/dev/null; then
+ if [[ -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar ]]; then
msg_info "Updating DUO Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar
curl_download "/tmp/guacamole-auth-duo.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-duo-${LATEST_SERVER}.tar.gz"
@@ -170,7 +170,7 @@ function update_script() {
fi
# LDAP Extension
- if compgen -G "/etc/guacamole/extensions/guacamole-auth-ldap-*.jar" >/dev/null; then
+ if [[ -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar ]]; then
msg_info "Updating LDAP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar
curl_download "/tmp/guacamole-auth-ldap.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-ldap-${LATEST_SERVER}.tar.gz"
@@ -182,7 +182,7 @@ function update_script() {
fi
# Quick Connect Extension
- if compgen -G "/etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar" >/dev/null; then
+ if [[ -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar ]]; then
msg_info "Updating Quick Connect Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar
curl_download "/tmp/guacamole-auth-quickconnect.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-quickconnect-${LATEST_SERVER}.tar.gz"
@@ -194,7 +194,7 @@ function update_script() {
fi
# History Recording Storage Extension
- if compgen -G "/etc/guacamole/extensions/guacamole-history-recording-storage-*.jar" >/dev/null; then
+ if [[ -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar ]]; then
msg_info "Updating History Recording Storage Extension"
rm -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar
curl_download "/tmp/guacamole-history-recording-storage.tar.gz" "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-history-recording-storage-${LATEST_SERVER}.tar.gz"
diff --git a/ct/authentik.sh b/ct/authentik.sh
index ec597f15c..c8b99db82 100644
--- a/ct/authentik.sh
+++ b/ct/authentik.sh
@@ -38,14 +38,13 @@ function update_script() {
NODE_VERSION="24" setup_nodejs
setup_go
- $STD uv cache clean
- UV_PYTHON_INSTALL_DIR="/usr/local/bin" PYTHON_VERSION="3.14.6" setup_uv
+ UV_PYTHON_INSTALL_DIR="/usr/local/bin" PYTHON_VERSION="3.14.3" setup_uv
RUST_PROFILE="minimal" RUST_TOOLCHAIN="stable" setup_rust
setup_yq
- AUTHENTIK_VERSION="version/2026.5.5"
+ AUTHENTIK_VERSION="version/2026.5.3"
# Source: https://github.com/goauthentik/fips/blob/main/Makefile#L26
- XMLSEC_VERSION="1.3.12"
+ XMLSEC_VERSION="1.3.11"
if check_for_gh_release "geoipupdate" "maxmind/geoipupdate"; then
fetch_and_deploy_gh_release "geoipupdate" "maxmind/geoipupdate" "binary"
diff --git a/ct/babybuddy.sh b/ct/babybuddy.sh
index b718a42ef..29fc7703a 100644
--- a/ct/babybuddy.sh
+++ b/ct/babybuddy.sh
@@ -40,8 +40,7 @@ function update_script() {
create_backup /opt/babybuddy/babybuddy/settings/production.py
msg_info "Cleaning old files"
- cd /opt/babybuddy || exit
- find . -mindepth 1 -maxdepth 1 ! -name '.venv' -exec rm -rf -- {} +
+ find . -mindepth 1 -maxdepth 1 ! -name '.venv' -exec rm -rf {} +
msg_ok "Cleaned old files"
fetch_and_deploy_gh_release "babybuddy" "babybuddy/babybuddy" "tarball"
@@ -52,7 +51,6 @@ function update_script() {
source .venv/bin/activate
$STD uv pip install -r requirements.txt
export DJANGO_SETTINGS_MODULE=babybuddy.settings.production
- $STD python manage.py makemigrations
$STD python manage.py migrate
msg_ok "Updated ${APP}"
diff --git a/ct/beaverhabits.sh b/ct/beaverhabits.sh
deleted file mode 100644
index 168be42d4..000000000
--- a/ct/beaverhabits.sh
+++ /dev/null
@@ -1,64 +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/daya0576/beaverhabits
-
-APP="BeaverHabits"
-var_tags="${var_tags:-habits;tracking;productivity}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-1024}"
-var_disk="${var_disk:-4}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/beaverhabits ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "beaverhabits" "daya0576/beaverhabits"; then
- msg_info "Stopping Service"
- systemctl stop beaverhabits
- msg_ok "Stopped Service"
-
- create_backup /opt/beaverhabits/.user
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "beaverhabits" "daya0576/beaverhabits" "tarball"
-
- msg_info "Syncing Dependencies"
- cd /opt/beaverhabits
- $STD uv sync --no-dev
- msg_ok "Synced Dependencies"
-
- restore_backup
-
- msg_info "Starting Service"
- systemctl start beaverhabits
- 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 "${GATEWAY}${BGN}http://${IP}:8080/register{CL}"
diff --git a/ct/birdnet-go.sh b/ct/birdnet-go.sh
index 6319219f9..39db9ca1f 100644
--- a/ct/birdnet-go.sh
+++ b/ct/birdnet-go.sh
@@ -37,7 +37,7 @@ function update_script() {
systemctl stop birdnet
msg_ok "Stopped Service"
- fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-$(arch_resolve)*.tar.gz"
+ fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-$(arch_resolve).tar.gz"
msg_info "Deploying Binary"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
diff --git a/ct/bookorbit.sh b/ct/bookorbit.sh
index b955ddd5a..7b0e95c13 100644
--- a/ct/bookorbit.sh
+++ b/ct/bookorbit.sh
@@ -53,7 +53,6 @@ function update_script() {
mkdir -p /opt/bookorbit/server/migrations
cp -r /opt/bookorbit/server/src/db/migrations/. /opt/bookorbit/server/migrations/
chmod +x /opt/bookorbit/server/bin/kepubify/*
- restore_backup
APP_VER=$(cat ~/.bookorbit)
sed -i "s/^APP_VERSION=.*/APP_VERSION=v$APP_VER/" /opt/bookorbit/.env
msg_ok "Rebuilt Application"
diff --git a/ct/cliproxyapi.sh b/ct/cliproxyapi.sh
index 40f9f2b1f..9eb49a1a6 100644
--- a/ct/cliproxyapi.sh
+++ b/ct/cliproxyapi.sh
@@ -36,12 +36,8 @@ function update_script() {
systemctl stop cliproxyapi
msg_ok "Stopped CLIProxyAPI"
- create_backup /opt/cliproxyapi/config.yaml
-
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cliproxyapi" "router-for-me/CLIProxyAPI" "prebuild" "latest" "/opt/cliproxyapi" "CLIProxyAPI_*_linux_$(arch_resolve "amd64" "aarch64").tar.gz"
- restore_backup
-
msg_info "Starting CLIProxyAPI"
systemctl start cliproxyapi
msg_ok "Started CLIProxyAPI"
diff --git a/ct/docmost.sh b/ct/docmost.sh
index 1c6271c98..c3392c585 100644
--- a/ct/docmost.sh
+++ b/ct/docmost.sh
@@ -39,6 +39,7 @@ function update_script() {
create_backup /opt/docmost/.env \
/opt/docmost/data
+
fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball"
restore_backup
@@ -53,11 +54,9 @@ function update_script() {
sed -i '/^@Module({$/i @Global()' /opt/docmost/apps/server/src/core/core.module.ts
fi
- msg_info "Configuring Docmost"
- cd /opt/docmost
$STD pnpm install --force
$STD pnpm build
- msg_ok "Configured Docmost"
+ msg_ok "Updated ${APP}"
msg_info "Starting Service"
systemctl start docmost
diff --git a/ct/docuseal.sh b/ct/docuseal.sh
index 9fbdca313..d856d1694 100644
--- a/ct/docuseal.sh
+++ b/ct/docuseal.sh
@@ -35,8 +35,6 @@ function update_script() {
systemctl stop docuseal docuseal-sidekiq
msg_ok "Stopped Services"
- ensure_dependencies libleptonica-dev libleptonica6
-
create_backup /opt/docuseal/.env \
/opt/docuseal/data
diff --git a/ct/endurain.sh b/ct/endurain.sh
index cdfd6eb0a..934532aea 100644
--- a/ct/endurain.sh
+++ b/ct/endurain.sh
@@ -34,22 +34,31 @@ function update_script() {
systemctl stop endurain
msg_ok "Stopped Service"
- create_backup /opt/endurain/.env /opt/endurain/frontend/dist/env.js
+ msg_info "Creating Backup"
+ cp /opt/endurain/.env /opt/endurain.env
+ cp /opt/endurain/frontend/dist/env.js /opt/endurain.env.js
+ msg_ok "Created Backup"
+
CLEAN_INSTALL=1 fetch_and_deploy_codeberg_release "endurain" "endurain-project/endurain" "tarball" "latest" "/opt/endurain"
msg_info "Preparing Update"
cd /opt/endurain
- rm -rf /opt/endurain/{docs,example.env,screenshot_01.png} /opt/endurain/docker* /opt/endurain/*.yml
+ rm -rf \
+ /opt/endurain/{docs,example.env,screenshot_01.png} \
+ /opt/endurain/docker* \
+ /opt/endurain/*.yml
+ cp /opt/endurain.env /opt/endurain/.env
+ rm /opt/endurain.env
msg_ok "Prepared Update"
msg_info "Updating Frontend"
cd /opt/endurain/frontend
$STD npm ci
$STD npm run build
+ cp /opt/endurain.env.js /opt/endurain/frontend/dist/env.js
+ rm /opt/endurain.env.js
msg_ok "Updated Frontend"
- restore_backup
-
msg_info "Updating Backend"
cd /opt/endurain/backend
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
diff --git a/ct/esphome.sh b/ct/esphome.sh
index 086be0e83..4dcf1ea06 100644
--- a/ct/esphome.sh
+++ b/ct/esphome.sh
@@ -28,7 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
- ensure_dependencies libusb-1.0-0
msg_info "Stopping Service"
systemctl stop esphome-device-builder 2>/dev/null || true
diff --git a/ct/fileflows.sh b/ct/fileflows.sh
index 3f72cef69..1f33d2dd0 100644
--- a/ct/fileflows.sh
+++ b/ct/fileflows.sh
@@ -31,83 +31,28 @@ function update_script() {
exit
fi
- local proceed=false
+ update_available=$(curl -fsSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable)
+ if [[ "${update_available}" == "true" ]]; then
+ msg_info "Stopping Service"
+ systemctl --all stop 'fileflows*'
+ msg_info "Stopped Service"
- if systemctl list-unit-files 'fileflows.service' --no-legend 2>/dev/null | grep -q '^fileflows\.service'; then
- tmp=$(mktemp)
- http_code=$(curl -sSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' -o "$tmp" -w '%{http_code}' 2>/dev/null) || http_code="000"
- if [[ "$http_code" == "200" ]]; then
- update_available=$(jq -r '.UpdateAvailable // false' "$tmp" 2>/dev/null)
- rm -f "$tmp"
- if [[ "${update_available}" == "true" ]]; then
- proceed=true
- else
- msg_ok "No update required. ${APP} is already at latest version"
- exit
- fi
- else
- rm -f "$tmp"
- if [[ "$http_code" == "401" ]]; then
- msg_warn "Could not check for updates: API returned 401 (security may be enabled)."
- else
- msg_warn "Could not check for updates: API unreachable (HTTP ${http_code})."
- fi
- if [[ "${FORCE_UPDATE:-}" == "1" ]]; then
- proceed=true
- else
- read -r -p "${TAB3}Force update without version check? [y/N]: " CONFIRM
- if [[ "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
- proceed=true
- else
- msg_error "Update aborted."
- exit
- fi
- fi
- fi
+ msg_info "Creating Backup"
+ ls /opt/*.tar.gz &>/dev/null && rm -f /opt/*.tar.gz
+ backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz"
+ tar -czf "$backup_filename" -C /opt/fileflows Data
+ msg_ok "Backup Created"
+
+ fetch_and_deploy_from_url "https://fileflows.com/downloads/zip" "/opt/fileflows"
+
+ msg_info "Starting Service"
+ systemctl --all start 'fileflows*'
+ msg_ok "Started Service"
+ msg_ok "Updated successfully!"
else
- proceed=true
+ msg_ok "No update required. ${APP} is already at latest version"
fi
- if [[ "$proceed" != "true" ]]; then
- exit
- fi
-
- msg_info "Stopping Service"
- systemctl --all stop 'fileflows*'
- msg_ok "Stopped Service"
-
- msg_info "Creating Backup"
- ls /opt/*.tar.gz &>/dev/null && rm -f /opt/*.tar.gz
- backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz"
- tar -czf "$backup_filename" -C /opt/fileflows Data
- msg_ok "Backup Created"
-
- msg_info "Ensuring ASP.NET Core Runtime"
- if [[ "$(arch_resolve)" == "arm64" ]]; then
- if [[ ! -x /usr/lib/dotnet10/dotnet ]]; then
- curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
- $STD bash /tmp/dotnet-install.sh --channel 10.0 --runtime aspnetcore --install-dir /usr/lib/dotnet10
- ln -sf /usr/lib/dotnet10/dotnet /usr/bin/dotnet
- rm -f /tmp/dotnet-install.sh
- fi
- elif ! is_package_installed "aspnetcore-runtime-10.0"; then
- $STD apt remove -y aspnetcore-runtime-8.0 aspnetcore-runtime-9.0 2>/dev/null || true
- setup_deb822_repo \
- "microsoft" \
- "https://packages.microsoft.com/keys/microsoft-2025.asc" \
- "https://packages.microsoft.com/debian/13/prod/" \
- "trixie"
- $STD apt install -y aspnetcore-runtime-10.0
- fi
- msg_ok "Ensured ASP.NET Core Runtime"
-
- fetch_and_deploy_from_url "https://fileflows.com/downloads/zip" "/opt/fileflows"
-
- msg_info "Starting Service"
- systemctl --all start 'fileflows*'
- msg_ok "Started Service"
- msg_ok "Updated successfully!"
-
exit
}
diff --git a/ct/fireshare.sh b/ct/fireshare.sh
index f10be013b..296cb6c01 100644
--- a/ct/fireshare.sh
+++ b/ct/fireshare.sh
@@ -35,22 +35,12 @@ function update_script() {
systemctl stop fireshare
msg_ok "Stopped Service"
- create_backup /opt/fireshare/fireshare.env
+ mv /opt/fireshare/fireshare.env /opt
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "fireshare" "ShaneIsrael/fireshare" "tarball"
- restore_backup
+ mv /opt/fireshare.env /opt/fireshare
rm -f /usr/local/bin/fireshare
- if ! grep -q "__FIRESHARE_PORT__" /etc/nginx/nginx.conf; then
- cp /opt/fireshare/app/nginx/prod.conf /etc/nginx/nginx.conf
- sed -i 's|root /processed/|root /opt/fireshare-processed/|g' /etc/nginx/nginx.conf
- sed -i 's/^user[[:space:]]\+nginx;/user root;/' /etc/nginx/nginx.conf
- sed -i 's|root[[:space:]]\+/app/build;|root /opt/fireshare/app/client/build;|' /etc/nginx/nginx.conf
- sed -i 's/__FIRESHARE_PORT__/80/g' /etc/nginx/nginx.conf
- cp /opt/fireshare/app/nginx/error.html /etc/nginx/
- cp /opt/fireshare/app/nginx/api_unavailable.html /etc/nginx/
- fi
- msg_info "Configuring Fireshare"
-
+ msg_info "Updating Fireshare"
cd /opt/fireshare
$STD uv venv --clear
$STD .venv/bin/python -m ensurepip --upgrade
@@ -63,10 +53,13 @@ function update_script() {
export VIDEO_DIRECTORY=/opt/fireshare-videos
export PROCESSED_DIRECTORY=/opt/fireshare-processed
$STD uv run flask db upgrade
+
+ msg_info "Building Fireshare Client"
cd /opt/fireshare/app/client
$STD npm install
$STD npm run build
- msg_ok "Configured Fireshare"
+ msg_ok "Built Fireshare Client"
+ msg_ok "Updated Fireshare"
msg_info "Starting Service"
systemctl start fireshare
diff --git a/ct/grav.sh b/ct/grav.sh
deleted file mode 100644
index 9271a029e..000000000
--- a/ct/grav.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: Raffaele (rafspiny)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://getgrav.org/
-
-APP="Grav"
-var_tags="${var_tags:-cms}"
-var_cpu="${var_cpu:-1}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-no}"
-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/grav" ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "grav" "getgrav/grav"; then
- msg_info "Creating Backup"
- cd /opt/grav
- bin/grav backup -nq
- msg_ok "Backup Created"
- bin/gpm self-upgrade -y
- cd -
- chown -R www-data:www-data /opt/grav
- msg_ok "Update Successful"
- 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 "${GATEWAY}${BGN}http://${IP}:80${CL}"
diff --git a/ct/headers/affine b/ct/headers/affine
deleted file mode 100644
index 0e1d759f0..000000000
--- a/ct/headers/affine
+++ /dev/null
@@ -1,6 +0,0 @@
- ___ _____________ _ ________
- / | / ____/ ____(_) | / / ____/
- / /| | / /_ / /_ / / |/ / __/
- / ___ |/ __/ / __/ / / /| / /___
-/_/ |_/_/ /_/ /_/_/ |_/_____/
-
diff --git a/ct/headers/beaverhabits b/ct/headers/beaverhabits
deleted file mode 100644
index 0a11d4242..000000000
--- a/ct/headers/beaverhabits
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ __ __ __ _ __
- / __ )___ ____ __ _____ _____/ / / /___ _/ /_ (_) /______
- / __ / _ \/ __ `/ | / / _ \/ ___/ /_/ / __ `/ __ \/ / __/ ___/
- / /_/ / __/ /_/ /| |/ / __/ / / __ / /_/ / /_/ / / /_(__ )
-/_____/\___/\__,_/ |___/\___/_/ /_/ /_/\__,_/_.___/_/\__/____/
-
diff --git a/ct/headers/grav b/ct/headers/grav
deleted file mode 100644
index 3e041ab1e..000000000
--- a/ct/headers/grav
+++ /dev/null
@@ -1,6 +0,0 @@
- ______
- / ____/________ __ __
- / / __/ ___/ __ `/ | / /
-/ /_/ / / / /_/ /| |/ /
-\____/_/ \__,_/ |___/
-
diff --git a/ct/headers/invidious b/ct/headers/invidious
deleted file mode 100644
index c858744dd..000000000
--- a/ct/headers/invidious
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ _ ___
- / _/___ _ __(_)___/ (_)___ __ _______
- / // __ \ | / / / __ / / __ \/ / / / ___/
- _/ // / / / |/ / / /_/ / / /_/ / /_/ (__ )
-/___/_/ /_/|___/_/\__,_/_/\____/\__,_/____/
-
diff --git a/ct/headers/leafwiki b/ct/headers/leafwiki
deleted file mode 100644
index dcfacbddf..000000000
--- a/ct/headers/leafwiki
+++ /dev/null
@@ -1,6 +0,0 @@
- __ _____ ___ __ _
- / / ___ ____ _/ __/ | / (_) /__(_)
- / / / _ \/ __ `/ /_ | | /| / / / //_/ /
- / /___/ __/ /_/ / __/ | |/ |/ / / ,< / /
-/_____/\___/\__,_/_/ |__/|__/_/_/|_/_/
-
diff --git a/ct/headers/localagi b/ct/headers/localagi
deleted file mode 100644
index c47da9aac..000000000
--- a/ct/headers/localagi
+++ /dev/null
@@ -1,6 +0,0 @@
- __ _____ __________
- / / ____ _________ _/ / | / ____/ _/
- / / / __ \/ ___/ __ `/ / /| |/ / __ / /
- / /___/ /_/ / /__/ /_/ / / ___ / /_/ // /
-/_____/\____/\___/\__,_/_/_/ |_\____/___/
-
diff --git a/ct/headers/nexterm b/ct/headers/nexterm
deleted file mode 100644
index 7d52bc561..000000000
--- a/ct/headers/nexterm
+++ /dev/null
@@ -1,6 +0,0 @@
- _ __ __
- / | / /__ _ __/ /____ _________ ___
- / |/ / _ \| |/_/ __/ _ \/ ___/ __ `__ \
- / /| / __/> /_/ __/ / / / / / / /
-/_/ |_/\___/_/|_|\__/\___/_/ /_/ /_/ /_/
-
diff --git a/ct/headers/notediscovery b/ct/headers/notediscovery
deleted file mode 100644
index df51d962d..000000000
--- a/ct/headers/notediscovery
+++ /dev/null
@@ -1,6 +0,0 @@
- _ __ __ ____ _
- / | / /___ / /____ / __ \(_)_____________ _ _____ _______ __
- / |/ / __ \/ __/ _ \/ / / / / ___/ ___/ __ \ | / / _ \/ ___/ / / /
- / /| / /_/ / /_/ __/ /_/ / (__ ) /__/ /_/ / |/ / __/ / / /_/ /
-/_/ |_/\____/\__/\___/_____/_/____/\___/\____/|___/\___/_/ \__, /
- /____/
diff --git a/ct/headers/oxicloud b/ct/headers/oxicloud
deleted file mode 100644
index b48c6ee29..000000000
--- a/ct/headers/oxicloud
+++ /dev/null
@@ -1,6 +0,0 @@
- ____ _ ________ __
- / __ \_ __(_) ____/ /___ __ ______/ /
- / / / / |/_/ / / / / __ \/ / / / __ /
-/ /_/ /> / /___/ / /_/ / /_/ / /_/ /
-\____/_/|_/_/\____/_/\____/\__,_/\__,_/
-
diff --git a/ct/headers/squid b/ct/headers/squid
deleted file mode 100644
index 3d826ef75..000000000
--- a/ct/headers/squid
+++ /dev/null
@@ -1,6 +0,0 @@
- _____ _ __
- / ___/____ ___ __(_)___/ /
- \__ \/ __ `/ / / / / __ /
- ___/ / /_/ / /_/ / / /_/ /
-/____/\__, /\__,_/_/\__,_/
- /_/
diff --git a/ct/headers/sync-in b/ct/headers/sync-in
deleted file mode 100644
index f5ae41c66..000000000
--- a/ct/headers/sync-in
+++ /dev/null
@@ -1,6 +0,0 @@
- _____ _
- / ___/__ ______ _____ (_)___
- \__ \/ / / / __ \/ ___/_____/ / __ \
- ___/ / /_/ / / / / /__/_____/ / / / /
-/____/\__, /_/ /_/\___/ /_/_/ /_/
- /____/
diff --git a/ct/headers/yuvomi b/ct/headers/yuvomi
deleted file mode 100644
index 3247d3dcc..000000000
--- a/ct/headers/yuvomi
+++ /dev/null
@@ -1,6 +0,0 @@
-__ __ _
-\ \/ /_ ___ ______ ____ ___ (_)
- \ / / / / | / / __ \/ __ `__ \/ /
- / / /_/ /| |/ / /_/ / / / / / / /
-/_/\__,_/ |___/\____/_/ /_/ /_/_/
-
diff --git a/ct/immich.sh b/ct/immich.sh
index 1ea66f467..48ae7ceda 100644
--- a/ct/immich.sh
+++ b/ct/immich.sh
@@ -110,7 +110,7 @@ EOF
msg_ok "Image-processing libraries up to date"
fi
- RELEASE="v3.0.3"
+ RELEASE="v3.0.1"
if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
if [[ $(cat ~/.immich) > "2.5.1" ]]; then
msg_info "Enabling Maintenance Mode"
@@ -124,9 +124,7 @@ EOF
systemctl stop immich-web
systemctl stop immich-ml
msg_ok "Stopped Services"
- VCHORD_RELEASE="1.1.1"
- PG_VERSION=$(ls /etc/postgresql/ 2>/dev/null | sort -V | tail -1)
- PG_VERSION=${PG_VERSION:-16}
+ VCHORD_RELEASE="1.0.0"
[[ -f ~/.vchord_version ]] && mv ~/.vchord_version ~/.vectorchord
if check_for_gh_release "VectorChord" "tensorchord/VectorChord" "${VCHORD_RELEASE}" "updated together with Immich after testing"; then
# dead tuples in smart_search/face_search make the REINDEX below fail with
@@ -134,7 +132,7 @@ EOF
# while still on the old extension version, a post-upgrade vacuum errors instead
$STD sudo -u postgres psql -d immich -c "VACUUM (ANALYZE) smart_search;"
$STD sudo -u postgres psql -d immich -c "VACUUM (ANALYZE) face_search;"
- fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-${PG_VERSION}-vchord_*_$(arch_resolve).deb"
+ fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-16-vchord_*_$(arch_resolve).deb"
systemctl restart postgresql
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vector UPDATE;"
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;"
@@ -330,27 +328,6 @@ EOF
systemctl daemon-reload
fi
- # MickLesk temporary patch for HEIC thumbnail gen
- msg_info "Patching media.repository.js"
- MEDIA_REPO_JS="/opt/immich/app/dist/repositories/media.repository.js"
- if [[ -f "$MEDIA_REPO_JS" ]]; then
- python3 - <<'PY'
-from pathlib import Path
-p = Path('/opt/immich/app/dist/repositories/media.repository.js')
-s = p.read_text()
-old = "(0, sharp_1.default)(input).metadata()"
-new = "(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()"
-if new in s:
- print('hotfix already there')
-elif old in s:
- p.write_text(s.replace(old, new, 1))
- print('hotfix applied')
-else:
- print('pattern not found, skipped')
-PY
- fi
- msg_ok "Patched media.repository.js"
-
# chown excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
@@ -501,7 +478,6 @@ function compile_libvips() {
$STD git clone https://github.com/libvips/libvips.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBVIPS_REVISION"
- $STD git apply "$BASE_DIR"/server/sources/libvips-patches/0001-put-other-loaders-ahead-of-dcrawload.patch
$STD meson setup build --buildtype=release --libdir=lib -Dintrospection=disabled -Dtiff=disabled
cd build
$STD ninja install
diff --git a/ct/invidious.sh b/ct/invidious.sh
deleted file mode 100644
index b3b68a632..000000000
--- a/ct/invidious.sh
+++ /dev/null
@@ -1,77 +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: vhsdream
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/iv-org/invidious
-
-APP="Invidious"
-var_tags="${var_tags:-streaming}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-4096}"
-var_disk="${var_disk:-20}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/invidious ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "Invidious" "iv-org/invidious"; then
- msg_info "Stopping services"
- $STD systemctl stop invidious-companion invidious
- msg_ok "Stopped services"
-
- create_backup /opt/invidious/config/config.yml
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Invidious" "iv-org/invidious" "tarball" "latest" "/opt/invidious"
- if check_for_gh_release "Invidious-Companion" "iv-org/invidious-companion"; then
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Invidious-Companion" "iv-org/invidious-companion" "prebuild" "latest" "/opt/invidious-companion" "invidious_companion-$(arch_resolve x86_64 aarch64)-unknown-linux-gnu.tar.gz"
- fi
-
- msg_info "Rebuilding Invidious"
- cd /opt/invidious
- INVIDIOUS_VERSION="$(cat ~/.invidious 2>/dev/null || echo "unknown")"
- INVIDIOUS_VERSION="${INVIDIOUS_VERSION#v}"
- sed -i \
- -e "s~^\(\s*CURRENT_BRANCH\s*=\).*~\1 \"master\"~" \
- -e "s~^\(\s*CURRENT_COMMIT\s*=\).*~\1 \"\"~" \
- -e "s~^\(\s*CURRENT_VERSION\s*=\).*~\1 \"${INVIDIOUS_VERSION}\"~" \
- -e "s~^\(\s*CURRENT_TAG\s*=\).*~\1 \"${INVIDIOUS_VERSION}\"~" \
- -e "s~^\(\s*ASSET_COMMIT\s*=\).*~\1 \"\"~" \
- src/invidious.cr
- $STD make
- msg_ok "Rebuilt Invidious"
-
- restore_backup
-
- msg_info "Starting services"
- $STD systemctl start invidious invidious-companion
- 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 "${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/leafwiki.sh b/ct/leafwiki.sh
deleted file mode 100644
index 20633cb57..000000000
--- a/ct/leafwiki.sh
+++ /dev/null
@@ -1,57 +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/perber/leafwiki
-
-APP="LeafWiki"
-var_tags="${var_tags:-wiki;markdown;notes}"
-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_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -f /usr/local/bin/leafwiki ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "leafwiki" "perber/leafwiki"; then
- msg_info "Stopping Service"
- systemctl stop leafwiki
- msg_ok "Stopped Service"
-
- create_backup /opt/leafwiki/data
- fetch_and_deploy_gh_release "leafwiki" "perber/leafwiki" "singlefile" "latest" "/usr/local/bin" "leafwiki-v*-linux-$(arch_resolve)"
- restore_backup
-
- msg_info "Starting Service"
- systemctl start leafwiki
- 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 "${GATEWAY}${BGN}http://${IP}:8080${CL}"
diff --git a/ct/localagi.sh b/ct/localagi.sh
deleted file mode 100644
index b2f9fbe91..000000000
--- a/ct/localagi.sh
+++ /dev/null
@@ -1,67 +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: BillyOutlast
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/mudler/LocalAGI
-
-APP="LocalAGI"
-var_tags="${var_tags:-ai}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-4096}"
-var_disk="${var_disk:-20}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-no}"
-var_unprivileged="${var_unprivileged:-1}"
-var_gpu="${var_gpu:-no}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/localagi ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "localagi" "mudler/LocalAGI"; then
- msg_info "Stopping Service"
- systemctl stop localagi
- msg_ok "Stopped Service"
-
- create_backup /opt/localagi/.env
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "localagi" "mudler/LocalAGI" "tarball" "latest" "/opt/localagi"
- restore_backup
-
- msg_info "Building LocalAGI"
- cd /opt/localagi/webui/react-ui
- $STD bun install
- $STD bun run build
- cd /opt/localagi
- $STD go build -o /usr/local/bin/localagi
- msg_ok "Updated LocalAGI successfully"
-
- msg_info "Starting Service"
- systemctl start localagi
- msg_ok "Started Service"
- msg_ok "Updated successfully!"
- exit
- 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 "${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/ct/lychee.sh b/ct/lychee.sh
index 7adfff87b..887d1f3ac 100644
--- a/ct/lychee.sh
+++ b/ct/lychee.sh
@@ -31,38 +31,33 @@ function update_script() {
fi
if check_for_gh_release "lychee" "LycheeOrg/Lychee"; then
- PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')
-
msg_info "Stopping Services"
- systemctl stop caddy php${PHP_VER}-fpm
+ systemctl stop caddy
msg_ok "Stopped Services"
- create_backup /opt/lychee/.env \
- /opt/lychee/storage \
- /opt/lychee/public/uploads \
- /opt/lychee/public/dist
+ msg_info "Backing up Data"
+ cp /opt/lychee/.env /opt/lychee.env.bak
+ cp -r /opt/lychee/storage /opt/lychee_storage_backup
+ msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "lychee" "LycheeOrg/Lychee" "prebuild" "latest" "/opt/lychee" "Lychee.zip"
- restore_backup
+ msg_info "Restoring Data"
+ cp /opt/lychee.env.bak /opt/lychee/.env
+ rm -f /opt/lychee.env.bak
+ cp -r /opt/lychee_storage_backup/. /opt/lychee/storage
+ rm -rf /opt/lychee_storage_backup
+ msg_ok "Restored Data"
msg_info "Updating Application"
cd /opt/lychee
$STD php artisan migrate --force
- $STD php artisan config:clear
- $STD php artisan cache:clear
$STD php artisan optimize:clear
- $STD php artisan optimize
- chown -R www-data:www-data /opt/lychee
- chmod -R 775 /opt/lychee/storage /opt/lychee/bootstrap/cache \
- /opt/lychee/public/dist /opt/lychee/public/uploads
- if [[ "${VERBOSE:-no}" = "yes" ]]; then
- php artisan lychee:diagnostics || true
- fi
+ chmod -R 775 /opt/lychee/storage /opt/lychee/bootstrap/cache
msg_ok "Updated Application"
msg_info "Starting Services"
- systemctl start caddy php${PHP_VER}-fpm
+ systemctl start caddy
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
diff --git a/ct/n8n.sh b/ct/n8n.sh
index 658a19b6c..8f9cb483b 100644
--- a/ct/n8n.sh
+++ b/ct/n8n.sh
@@ -45,7 +45,7 @@ EOF
systemctl daemon-reload
fi
- $STD npm install -g n8n@latest
+ $STD npm install -g n8n@2.27.5
systemctl restart n8n
msg_ok "Updated n8n"
msg_ok "Updated successfully!"
diff --git a/ct/nexterm.sh b/ct/nexterm.sh
deleted file mode 100644
index dd67c4697..000000000
--- a/ct/nexterm.sh
+++ /dev/null
@@ -1,66 +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: Mathias Wagner (gnmyt)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://nexterm.dev/
-
-APP="Nexterm"
-var_tags="${var_tags:-server-management}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-6}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -f /opt/nexterm/server/nexterm-server ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "nexterm-engine" "gnmyt/Nexterm"; then
- msg_info "Stopping nexterm-engine"
- systemctl stop nexterm-engine
- msg_ok "Stopped nexterm-engine"
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "nexterm-engine" "gnmyt/Nexterm" "prebuild" "latest" "/opt/nexterm/engine" "nexterm-engine-linux-$(arch_resolve "x64" "arm64").tar.gz"
-
- msg_info "Starting nexterm-engine"
- systemctl start nexterm-engine
- msg_ok "Started nexterm-engine"
- fi
-
- if check_for_gh_release "nexterm-server" "gnmyt/Nexterm"; then
- msg_info "Stopping nexterm-server"
- systemctl stop nexterm-server
- msg_ok "Stopped nexterm-server"
-
- fetch_and_deploy_gh_release "nexterm-server" "gnmyt/Nexterm" "singlefile" "latest" "/opt/nexterm/server" "nexterm-server-linux-$(arch_resolve "x64" "arm64")"
-
- msg_info "Starting nexterm-server"
- systemctl start nexterm-server
- msg_ok "Started nexterm-server"
- 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 "${GATEWAY}${BGN}http://${IP}:6989${CL}"
diff --git a/ct/notediscovery.sh b/ct/notediscovery.sh
deleted file mode 100644
index 3b15fd0c7..000000000
--- a/ct/notediscovery.sh
+++ /dev/null
@@ -1,64 +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/gamosoft/NoteDiscovery
-
-APP="NoteDiscovery"
-var_tags="${var_tags:-notes;wiki;knowledge-base}"
-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_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/notediscovery ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "notediscovery" "gamosoft/NoteDiscovery"; then
- msg_info "Stopping Service"
- systemctl stop notediscovery
- msg_ok "Stopped Service"
-
- create_backup /opt/notediscovery/data /opt/notediscovery/config.yaml
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "notediscovery" "gamosoft/NoteDiscovery" "tarball"
-
- msg_info "Syncing Dependencies"
- cd /opt/notediscovery
- $STD uv sync --no-dev
- msg_ok "Synced Dependencies"
-
- restore_backup
-
- msg_info "Starting Service"
- systemctl start notediscovery
- 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 "${GATEWAY}${BGN}http://${IP}:8000${CL}"
diff --git a/ct/opencloud.sh b/ct/opencloud.sh
index 51485fec3..b64dc34d0 100644
--- a/ct/opencloud.sh
+++ b/ct/opencloud.sh
@@ -30,7 +30,7 @@ function update_script() {
exit
fi
- RELEASE="v7.3.0"
+ RELEASE="v7.2.0"
if check_for_gh_release "OpenCloud" "opencloud-eu/opencloud" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
msg_info "Stopping services"
systemctl stop opencloud opencloud-wopi
diff --git a/ct/oxicloud.sh b/ct/oxicloud.sh
deleted file mode 100644
index bee864391..000000000
--- a/ct/oxicloud.sh
+++ /dev/null
@@ -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: vhsdream
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/DioCrafts/OxiCloud
-
-APP="OxiCloud"
-var_tags="${var_tags:-files;documents}"
-var_cpu="${var_cpu:-4}"
-var_ram="${var_ram:-6144}"
-var_disk="${var_disk:-20}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/oxicloud ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "OxiCloud" "DioCrafts/OxiCloud"; then
- msg_info "Stopping OxiCloud"
- systemctl stop oxicloud
- msg_ok "Stopped OxiCloud"
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "OxiCloud" "DioCrafts/OxiCloud" "tarball" "latest" "/opt/oxicloud"
- TOOLCHAIN="$(grep -oP 'FROM\s+rust:\K[0-9]+\.[0-9]+(\.[0-9]+)?' /opt/oxicloud/Dockerfile | head -1)"
- RUST_TOOLCHAIN="${TOOLCHAIN:-stable}" setup_rust
-
- msg_info "Building Frontend SPA"
- cd /opt/oxicloud/frontend
- $STD npm ci
- $STD npm run build
- msg_ok "Built Frontend SPA"
-
- msg_info "Updating OxiCloud (Patience)"
- set -a
- source /etc/oxicloud/.env
- set +a
- cd /opt/oxicloud
- export DATABASE_URL
- export RUSTFLAGS="-C target-cpu=native"
- RAM_MB=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo)
- CARGO_JOBS=$((RAM_MB / 2560))
- [[ $CARGO_JOBS -lt 1 ]] && CARGO_JOBS=1
- [[ $CARGO_JOBS -gt $(nproc) ]] && CARGO_JOBS=$(nproc)
- $STD cargo build --release -j "$CARGO_JOBS" --bin oxicloud --bin migrate-nfc-filenames
- mv target/release/oxicloud /usr/local/bin/oxicloud
- mv target/release/migrate-nfc-filenames /usr/local/bin/migrate-nfc-filenames
- chmod +x /usr/local/bin/oxicloud /usr/local/bin/migrate-nfc-filenames
- rm -f /usr/bin/oxicloud
- rm -rf /opt/oxicloud/static
- mv /opt/oxicloud/static-dist /opt/oxicloud/static
- rm -rf /opt/oxicloud/target /opt/oxicloud/frontend/node_modules
- msg_ok "Updated OxiCloud"
-
- msg_info "Starting OxiCloud"
- systemctl start oxicloud
- msg_ok "Started OxiCloud"
- 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 "${GATEWAY}${BGN}http://${IP}:8086${CL}"
diff --git a/ct/pangolin.sh b/ct/pangolin.sh
index fe5b787a9..08d604277 100644
--- a/ct/pangolin.sh
+++ b/ct/pangolin.sh
@@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin
APP="Pangolin"
-PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.20.0}"
+PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.4}"
var_tags="${var_tags:-proxy}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
@@ -33,15 +33,6 @@ function update_script() {
ensure_dependencies build-essential python3
- if ! command -v psql &>/dev/null; then
- msg_error "This installation uses SQLite and cannot be upgraded to Pangolin ${PANGOLIN_VERSION}."
- echo -e "${INFO}${YW}Starting with Pangolin 1.20.0, PostgreSQL is required as the database backend.${CL}"
- echo -e "${INFO}${YW}An automatic migration of your existing SQLite data is not supported.${CL}"
- echo -e "${INFO}${YW}Please create a new LXC with the Pangolin install script, which sets up PostgreSQL automatically.${CL}"
- echo -e "${INFO}${YW}Your current data is preserved in this container and can be manually migrated if needed.${CL}"
- exit 1
- fi
-
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "pangolin" "fosrl/pangolin" "$PANGOLIN_VERSION" "Pinned to a tested release because Pangolin's schema changes have repeatedly broken unattended updates. To try a newer version at your own risk, run: 'export PANGOLIN_VERSION=' and re-run update. If it breaks, please open an issue at https://github.com/community-scripts/ProxmoxVE/issues with the error log."; then
@@ -50,8 +41,13 @@ function update_script() {
systemctl stop gerbil
msg_info "Service stopped"
- DB_URL=$(sed -n 's/.*connection_string: "\(.*\)".*/\1/p' /opt/pangolin/config/config.yml)
- create_backup /opt/pangolin/config
+ msg_info "Creating backup"
+ tar -czf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin config
+ if [[ -f /opt/pangolin/config/db/db.sqlite ]]; then
+ cp -a /opt/pangolin/config/db/db.sqlite \
+ "/opt/pangolin/config/db/db.sqlite.pre-${PANGOLIN_VERSION}-$(date +%Y%m%d-%H%M%S).bak"
+ fi
+ msg_ok "Created backup"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_$(arch_resolve)"
@@ -59,21 +55,23 @@ function update_script() {
msg_info "Updating Pangolin"
cd /opt/pangolin
$STD npm ci
- $STD npm run set:pg
+ $STD npm run set:sqlite
$STD npm run set:oss
rm -rf server/private
- DATABASE_URL="$DB_URL" $STD npm run db:generate
+ $STD npm run db:generate
$STD npm run build
$STD npm run build:cli
cp -R .next/standalone ./
- cp -r server/migrations ./dist/init
chmod +x ./dist/cli.mjs
cp server/db/names.json ./dist/names.json
cp server/db/ios_models.json ./dist/ios_models.json
cp server/db/mac_models.json ./dist/mac_models.json
msg_ok "Updated Pangolin"
- restore_backup
+ msg_info "Restoring config"
+ tar -xzf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin --overwrite
+ rm -f /opt/pangolin_config_backup.tar.gz
+ msg_ok "Restored config"
if ! grep -q '^ExecStartPre=/usr/bin/node dist/migrations.mjs' /etc/systemd/system/pangolin.service 2>/dev/null; then
msg_info "Adding migration step to pangolin.service"
@@ -84,8 +82,13 @@ function update_script() {
msg_info "Running database migrations"
cd /opt/pangolin
+ SQLITE_DB="/opt/pangolin/config/db/db.sqlite"
+ if [[ -f "$SQLITE_DB" ]]; then
+ if ! sqlite3 "$SQLITE_DB" ".tables" 2>/dev/null | tr ' ' '\n' | grep -qx "statusHistory"; then
+ sqlite3 "$SQLITE_DB" "DELETE FROM versionMigrations;" 2>/dev/null || true
+ fi
+ fi
ENVIRONMENT=prod $STD node dist/migrations.mjs
-
msg_ok "Ran database migrations"
msg_info "Updating Badger plugin version"
@@ -109,4 +112,4 @@ description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW}Access it using the following URL:${CL}"
-echo -e "${GATEWAY}${BGN}https:// or http://${IP}:3002${CL}"
+echo -e "${GATEWAY}${BGN}https://${CL}"
diff --git a/ct/pocketid.sh b/ct/pocketid.sh
index 9ffc54426..6153b40c0 100755
--- a/ct/pocketid.sh
+++ b/ct/pocketid.sh
@@ -71,7 +71,7 @@ function update_script() {
cp /opt/pocket-id/.env /opt/env
fi
- fetch_and_deploy_gh_release "pocket-id" "pocket-id/pocket-id" "singlefile" "latest" "/opt/pocket-id/" "pocket-id_linux_$(arch_resolve)"
+ fetch_and_deploy_gh_release "pocket-id" "pocket-id/pocket-id" "singlefile" "latest" "/opt/pocket-id/" "pocket-id-linux-$(arch_resolve)"
mv /opt/env /opt/pocket-id/.env
msg_info "Starting Service"
diff --git a/ct/reitti.sh b/ct/reitti.sh
index 5980e6ae7..f160176d4 100644
--- a/ct/reitti.sh
+++ b/ct/reitti.sh
@@ -106,6 +106,13 @@ spring.servlet.multipart.max-file-size=5GB
spring.servlet.multipart.max-request-size=5GB
server.tomcat.max-part-count=100
+# Rqueue configuration
+rqueue.web.enable=false
+rqueue.job.enabled=false
+rqueue.message.durability.in-terminal-state=0
+rqueue.key.prefix=\${spring.cache.redis.key-prefix}
+rqueue.message.converter.provider.class=com.dedicatedcode.reitti.config.RQueueCustomMessageConverter
+
# Application-specific settings
reitti.server.advertise-uri=
@@ -161,81 +168,6 @@ PROPEOF
msg_ok "Rewrote application.properties (backup: application.properties.bak)"
fi
- # Migrate v4 -> v5: Remove Rqueue configuration (replaced by Quartz Scheduler)
- if grep -q "^rqueue\." /opt/reitti/application.properties 2>/dev/null; then
- msg_info "Migrating to v5: Removing Rqueue configuration"
- sed -i '/^# Rqueue configuration$/d; /^rqueue\./d' /opt/reitti/application.properties
- msg_ok "Removed Rqueue configuration"
- fi
-
- # Migrate v4 -> v5: Update application.properties and nginx tile cache for v5 compatibility
- if grep -q "^reitti\.process-data\.schedule=" /opt/reitti/application.properties 2>/dev/null; then
- msg_info "Migrating to v5: Updating application.properties"
- sed -i '/^reitti\.process-data\.schedule=/d' /opt/reitti/application.properties
- sed -i 's/^reitti\.import\.processing-idle-start-time=.*/reitti.import.grace-time-seconds=30/' /opt/reitti/application.properties
- sed -i 's/^spring\.datasource\.hikari\.maximum-pool-size=20$/spring.datasource.hikari.maximum-pool-size=30/' /opt/reitti/application.properties
- grep -q "devices" /opt/reitti/application.properties || \
- sed -i 's/^spring\.cache\.cache-names=\(.*\)$/spring.cache.cache-names=\1,devices,mapStyles,mapStyleJson/' /opt/reitti/application.properties
- grep -q "org.quartz.core.ErrorLogger" /opt/reitti/application.properties || \
- sed -i '/^logging\.level\.com\.dedicatedcode\.reitti=/a logging.level.org.quartz.core.ErrorLogger=FATAL' /opt/reitti/application.properties
- grep -q "^spring.servlet.multipart.resolve-lazily=" /opt/reitti/application.properties || \
- sed -i '/^spring\.servlet\.multipart\.max-request-size=/a spring.servlet.multipart.resolve-lazily=true' /opt/reitti/application.properties
- grep -q "^spring.mvc.async.request-timeout=" /opt/reitti/application.properties || \
- echo "spring.mvc.async.request-timeout=600000" >>/opt/reitti/application.properties
- if ! grep -q "^spring.quartz" /opt/reitti/application.properties; then
- cat >>/opt/reitti/application.properties <<'QUARTZEOF'
-
-# Quartz Scheduler configuration
-spring.quartz.job-store-type=jdbc
-spring.quartz.jdbc.initialize-schema=never
-spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
-spring.quartz.properties.org.quartz.jobStore.isClustered=false
-spring.quartz.properties.org.quartz.jobStore.tablePrefix=qrtz_
-spring.quartz.properties.org.quartz.threadPool.threadCount=5
-QUARTZEOF
- fi
- grep -q "^reitti.import.staging.cleanup.cron=" /opt/reitti/application.properties || \
- echo "reitti.import.staging.cleanup.cron=0 0 4 * * *" >>/opt/reitti/application.properties
- grep -q "^reitti.batching.max-batch-size=" /opt/reitti/application.properties || \
- printf "reitti.batching.max-batch-size=100\nreitti.batching.max-wait-time=5\n" >>/opt/reitti/application.properties
- grep -q "^reitti.jobs.cleanup.cron=" /opt/reitti/application.properties || \
- printf "reitti.jobs.cleanup.cron=0 0 4 * * ?\nreitti.jobs.cleanup.max-age-hours=24\n" >>/opt/reitti/application.properties
- grep -q "^reitti.db-janitor.schedule=" /opt/reitti/application.properties || \
- echo "reitti.db-janitor.schedule=0 0 4 * * ?" >>/opt/reitti/application.properties
- msg_ok "Updated application.properties for v5"
-
- if [[ -f /etc/nginx/nginx.conf ]]; then
- msg_info "Migrating to v5: Updating nginx tile cache configuration"
- cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.v5
- cat >/etc/nginx/nginx.conf <<'NGINXEOF'
-user www-data;
-
-events {
- worker_connections 1024;
-}
-http {
- resolver 1.1.1.1 8.8.8.8 valid=30s ipv6=off;
- proxy_cache_path /var/cache/nginx/tiles levels=1:2 keys_zone=tiles:10m max_size=1g inactive=30d use_temp_path=off;
- server {
- listen 80;
- location /custom/ {
- set $upstream_url $http_x_reitti_upstream_url;
- proxy_pass $upstream_url;
- proxy_set_header Host $proxy_host;
- proxy_set_header User-Agent "Reitti/1.0";
- proxy_cache tiles;
- proxy_cache_key $upstream_url;
- proxy_cache_valid 200 30d;
- proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
- }
- }
-}
-NGINXEOF
- systemctl reload nginx
- msg_ok "Updated nginx tile cache configuration"
- fi
- fi
-
if check_for_gh_release "reitti" "dedicatedcode/reitti"; then
msg_info "Stopping Service"
systemctl stop reitti
@@ -247,12 +179,10 @@ NGINXEOF
USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "reitti" "dedicatedcode/reitti" "singlefile" "latest" "/opt/reitti" "reitti-app.jar"
mv /opt/reitti/reitti-*.jar /opt/reitti/reitti.jar
- msg_warn "v5 runs a one-time database migration on first start (GPS points → device table). This may take several minutes on large datasets — do not interrupt the container."
msg_info "Starting Service"
systemctl start reitti
msg_ok "Started Service"
msg_ok "Updated successfully!"
- msg_warn "Post-upgrade: Verify each API token has a Device assigned in Settings → API Tokens. Tokens without a device cannot ingest location data in v5."
fi
exit
}
diff --git a/ct/sftpgo.sh b/ct/sftpgo.sh
index 5c6a79adf..d96f013d2 100644
--- a/ct/sftpgo.sh
+++ b/ct/sftpgo.sh
@@ -28,12 +28,6 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
-
- setup_deb822_repo \
- "sftpgo" \
- "https://oss.sftpgo.com/apt/gpg.key" \
- "https://oss.sftpgo.com/apt" \
- "trixie"
msg_info "Updating SFTPGo"
$STD apt update
diff --git a/ct/snapotter.sh b/ct/snapotter.sh
index ce2323f8f..2ebea2959 100644
--- a/ct/snapotter.sh
+++ b/ct/snapotter.sh
@@ -30,63 +30,19 @@ function update_script() {
exit
fi
- NEEDS_V2_MIGRATION=false
- grep -q '^DB_PATH=' /opt/snapotter_data/.env 2>/dev/null && NEEDS_V2_MIGRATION=true
- UPDATE_AVAILABLE=false
- check_for_gh_release "snapotter" "snapotter-hq/SnapOtter" && UPDATE_AVAILABLE=true
-
- if [[ "$NEEDS_V2_MIGRATION" == true || "$UPDATE_AVAILABLE" == true ]]; then
+ if check_for_gh_release "snapotter" "snapotter-hq/SnapOtter"; then
msg_info "Stopping Service"
systemctl stop snapotter
msg_ok "Stopped Service"
- PG_VERSION="17" setup_postgresql
- if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'snapotter'" | grep -qx '1'; then
- PG_DB_NAME="snapotter" PG_DB_USER="snapotter" setup_postgresql_db
- else
- PG_DB_NAME="snapotter"
- PG_DB_USER="snapotter"
- PG_DB_PASS=$(sed -n 's|^DATABASE_URL=postgres://snapotter:\([^@]*\)@.*|\1|p' /opt/snapotter_data/.env | head -n1)
- if [[ -z "$PG_DB_PASS" ]]; then
- msg_error "SnapOtter's PostgreSQL database exists, but its password is not available in /opt/snapotter_data/.env"
- exit 1
- fi
- fi
-
- msg_info "Installing Redis"
- $STD apt install -y redis-server
- if grep -q '^appendonly ' /etc/redis/redis.conf; then
- sed -i 's/^appendonly .*/appendonly yes/' /etc/redis/redis.conf
- else
- echo 'appendonly yes' >>/etc/redis/redis.conf
- fi
- $STD systemctl enable --now redis-server
- msg_ok "Installed Redis"
-
- msg_info "Migrating SnapOtter Configuration"
- sed -i '/^DB_PATH=/d; /^DATABASE_URL=/d; /^REDIS_URL=/d; /^SQLITE_MIGRATE_PATH=/d' /opt/snapotter_data/.env
- cat <>/opt/snapotter_data/.env
-DATABASE_URL=postgres://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
-REDIS_URL=redis://127.0.0.1:6379
-EOF
- if [[ -f /opt/snapotter_data/snapotter.db ]]; then
- echo 'SQLITE_MIGRATE_PATH=/opt/snapotter_data/snapotter.db' >>/opt/snapotter_data/.env
- fi
- if ! grep -q '^Requires=postgresql.service redis-server.service$' /etc/systemd/system/snapotter.service; then
- sed -i '/^After=/c\After=network-online.target postgresql.service redis-server.service' /etc/systemd/system/snapotter.service
- sed -i '/^\[Unit\]/a Wants=network-online.target\nRequires=postgresql.service redis-server.service' /etc/systemd/system/snapotter.service
- fi
- systemctl daemon-reload
- msg_ok "Migrated SnapOtter Configuration"
-
- if [[ "$UPDATE_AVAILABLE" == true ]]; then
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "snapotter" "snapotter-hq/SnapOtter" "prebuild" "latest" "/opt/snapotter" "snapotter-*-linux-amd64.tar.gz"
- fi
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "snapotter" "snapotter-hq/SnapOtter" "tarball"
msg_info "Updating SnapOtter"
- $STD uv python install 3.11
- $STD uv venv --seed --python 3.11 /opt/snapotter_data/ai/venv
- ln -sfn /opt/snapotter /app
+ cd /opt/snapotter
+ $STD npm pkg delete scripts.prepare
+ $STD pnpm install --frozen-lockfile
+ $STD pnpm --filter @snapotter/web build
+ sed -i 's/mediapipe==0.10.21/mediapipe>=0.10.21/' /opt/snapotter/docker/feature-manifest.json
msg_ok "Updated SnapOtter"
msg_info "Starting Service"
diff --git a/ct/squid.sh b/ct/squid.sh
deleted file mode 100644
index 1698fc395..000000000
--- a/ct/squid.sh
+++ /dev/null
@@ -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: 007hacky007
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.squid-cache.org/
-
-APP="Squid"
-var_tags="${var_tags:-proxy}"
-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_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
- if [[ ! -f /etc/squid/squid.conf ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
- msg_info "Updating Squid"
- $STD apt update
- $STD apt upgrade -y
- msg_ok "Updated Squid"
-
- msg_info "Validating Squid Configuration"
- $STD squid -k parse
- msg_ok "Validated Squid Configuration"
-
- msg_info "Restarting Squid"
- systemctl restart squid
- msg_ok "Restarted Squid"
- 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} Proxy endpoint:${CL}"
-echo -e "${TAB}${GATEWAY}${BGN}${IP}:3128${CL}"
diff --git a/ct/storyteller.sh b/ct/storyteller.sh
index 0e49e0196..df2f915c9 100644
--- a/ct/storyteller.sh
+++ b/ct/storyteller.sh
@@ -32,7 +32,7 @@ function update_script() {
NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
- if check_for_gl_release "storyteller" "storyteller-platform/storyteller" "" "" "web-v2"; then
+ if check_for_gl_release "storyteller" "storyteller-platform/storyteller"; then
msg_info "Stopping Service"
systemctl stop storyteller
msg_ok "Stopped Service"
@@ -41,7 +41,7 @@ function update_script() {
cp /opt/storyteller/.env /opt/storyteller_env.bak
msg_ok "Backed up Data"
- CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" "" "web-v2"
+ CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
msg_info "Restoring Configuration"
mv /opt/storyteller_env.bak /opt/storyteller/.env
diff --git a/ct/sync-in.sh b/ct/sync-in.sh
deleted file mode 100644
index 4b43c6dd4..000000000
--- a/ct/sync-in.sh
+++ /dev/null
@@ -1,65 +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/Sync-in/server
-
-APP="Sync-in"
-var_tags="${var_tags:-files;sync;collaboration}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-2048}"
-var_disk="${var_disk:-20}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/sync-in/node_modules/@sync-in ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "sync-in" "Sync-in/server"; then
- msg_info "Stopping Service"
- systemctl stop sync-in
- msg_ok "Stopped Service"
-
- msg_info "Updating Sync-in"
- $STD npm install --prefix /opt/sync-in "@sync-in/server@${CHECK_UPDATE_RELEASE#v}"
- msg_ok "Updated Sync-in"
-
- msg_info "Running Database Migrations"
- cd /opt/sync-in
- $STD npx sync-in-server migrate-db
- msg_ok "Ran Database Migrations"
-
- VERSION=$(node -pe "require('/opt/sync-in/node_modules/@sync-in/server/package.json').version" 2>/dev/null || echo "")
- [[ -n "$VERSION" ]] && echo "$VERSION" >~/.sync-in
-
- msg_info "Starting Service"
- systemctl start sync-in
- 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 "${GATEWAY}${BGN}http://${IP}:8080${CL}"
diff --git a/ct/trek.sh b/ct/trek.sh
index 9df637780..be958f75f 100644
--- a/ct/trek.sh
+++ b/ct/trek.sh
@@ -3,7 +3,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# 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/liketrek/TREK
+# Source: https://github.com/mauriceboe/TREK
APP="TREK"
var_tags="${var_tags:-travel;planning;collaboration}"
@@ -32,7 +32,7 @@ function update_script() {
NODE_VERSION="24" setup_nodejs
- if check_for_gh_release "trek" "liketrek/TREK"; then
+ if check_for_gh_release "trek" "mauriceboe/TREK"; then
MIGRATION=0
grep -qF "ExecStart=/usr/bin/node --import tsx src/index.ts" \
/etc/systemd/system/trek.service && MIGRATION=1
@@ -47,7 +47,7 @@ function update_script() {
/opt/trek/data \
/opt/trek/uploads
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "trek" "liketrek/TREK" "tarball"
+ CLEAN_INSTALL=1 fetch_and_deploy_gh_release "trek" "mauriceboe/TREK" "tarball"
msg_info "Building TREK"
cd /opt/trek
@@ -79,7 +79,7 @@ function update_script() {
cat </etc/systemd/system/trek.service
[Unit]
Description=TREK Travel Planner
-Documentation=https://github.com/liketrek/TREK
+Documentation=https://github.com/mauriceboe/TREK
After=network-online.target
Wants=network-online.target
diff --git a/ct/wanderer.sh b/ct/wanderer.sh
index bb0ec71cd..432963379 100644
--- a/ct/wanderer.sh
+++ b/ct/wanderer.sh
@@ -30,14 +30,12 @@ function update_script() {
exit
fi
- if check_for_gh_release "wanderer" "open-wanderer/wanderer"; then
+ if check_for_gh_release "wanderer" "Flomp/wanderer"; then
msg_info "Stopping service"
systemctl stop wanderer-web
msg_ok "Stopped service"
- create_backup /opt/wanderer/source/search
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source"
- restore_backup
+ fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source"
msg_info "Updating wanderer"
cd /opt/wanderer/source/db
@@ -46,13 +44,6 @@ function update_script() {
cd /opt/wanderer/source/web
$STD npm ci
$STD npm run build
- mkdir -p /opt/wanderer/data/plugins
- [[ -e /data/plugins ]] || ln -sfn /opt/wanderer/data/plugins /data/plugins
- msg_info "Installing wanderer plugins"
- for plugin in hammerhead komoot strava; do
- fetch_and_deploy_gh_release "wanderer-plugin-${plugin}" "open-wanderer/wanderer" "prebuild" "${CHECK_UPDATE_RELEASE:-latest}" "/opt/wanderer/data/plugins" "wanderer-plugin-${plugin}.tar.gz" || msg_warn "Failed to install wanderer plugin: ${plugin}"
- done
- msg_ok "Installed wanderer plugins"
msg_ok "Updated wanderer"
msg_info "Starting service"
diff --git a/ct/yuvomi.sh b/ct/yuvomi.sh
deleted file mode 100644
index 625a0aa61..000000000
--- a/ct/yuvomi.sh
+++ /dev/null
@@ -1,64 +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/ulsklyc/yuvomi
-
-APP="Yuvomi"
-var_tags="${var_tags:-family;planner;calendar}"
-var_cpu="${var_cpu:-2}"
-var_ram="${var_ram:-1024}"
-var_disk="${var_disk:-8}"
-var_os="${var_os:-debian}"
-var_version="${var_version:-13}"
-var_arm64="${var_arm64:-yes}"
-var_unprivileged="${var_unprivileged:-1}"
-
-header_info "$APP"
-variables
-color
-catch_errors
-
-function update_script() {
- header_info
- check_container_storage
- check_container_resources
-
- if [[ ! -d /opt/yuvomi ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-
- if check_for_gh_release "yuvomi" "ulsklyc/yuvomi"; then
- msg_info "Stopping Service"
- systemctl stop yuvomi
- msg_ok "Stopped Service"
-
- create_backup /opt/yuvomi/data /opt/yuvomi/.env
-
- CLEAN_INSTALL=1 fetch_and_deploy_gh_release "yuvomi" "ulsklyc/yuvomi" "tarball"
-
- msg_info "Installing Node.js Dependencies"
- cd /opt/yuvomi
- $STD npm ci --omit=dev
- msg_ok "Installed Node.js Dependencies"
-
- restore_backup
-
- msg_info "Starting Service"
- systemctl start yuvomi
- 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 "${GATEWAY}${BGN}http://${IP}:3000${CL}"
diff --git a/install/2fauth-install.sh b/install/2fauth-install.sh
index 61c8377ae..386b5c3de 100644
--- a/install/2fauth-install.sh
+++ b/install/2fauth-install.sh
@@ -43,7 +43,6 @@ $STD php artisan migrate:refresh
$STD php artisan passport:install -q -n
$STD php artisan storage:link
$STD php artisan config:cache
-$STD php artisan 2fauth:fix-passport-key-permissions
chown -R www-data: /opt/2fauth
chmod -R 755 /opt/2fauth
msg_ok "Setup 2fauth"
diff --git a/install/adventurelog-install.sh b/install/adventurelog-install.sh
index b480da0d9..10e664bc6 100644
--- a/install/adventurelog-install.sh
+++ b/install/adventurelog-install.sh
@@ -72,7 +72,6 @@ BODY_SIZE_LIMIT=Infinity
ORIGIN='http://$LOCAL_IP:3000'
EOF
cd /opt/adventurelog/frontend
-grep -q "^dangerouslyAllowAllBuilds:" ./pnpm-workspace.yaml 2>/dev/null || echo "dangerouslyAllowAllBuilds: true" >>./pnpm-workspace.yaml
$STD pnpm i
$STD pnpm build
msg_ok "Installed AdventureLog"
diff --git a/install/affine-install.sh b/install/affine-install.sh
deleted file mode 100644
index 50144d4e0..000000000
--- a/install/affine-install.sh
+++ /dev/null
@@ -1,217 +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/toeverything/AFFiNE
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y \
- build-essential \
- git \
- pkg-config \
- openssl \
- libssl-dev \
- libjemalloc2 \
- redis-server \
- nginx \
- cmake
-msg_ok "Installed Dependencies"
-
-PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql
-PG_DB_NAME="affine" PG_DB_USER="affine" setup_postgresql_db
-NODE_VERSION="22" setup_nodejs
-setup_rust
-
-fetch_and_deploy_gh_release "affine_app" "toeverything/AFFiNE" "tarball" "v0.27.0" "/opt/affine"
-
-msg_info "Setting up Directories"
-rm -rf /root/.affine
-mkdir -p /root/.affine/{storage,config}
-msg_ok "Set up Directories"
-
-msg_info "Configuring Environment"
-SECRET_KEY=$(openssl rand -hex 32)
-cat </opt/affine/.env
-NODE_ENV=production
-AFFINE_SERVER_PORT=3010
-AFFINE_SERVER_HOST=${LOCAL_IP}
-AFFINE_SERVER_EXTERNAL_URL=http://${LOCAL_IP}
-DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
-REDIS_SERVER_HOST=localhost
-REDIS_SERVER_PORT=6379
-AFFINE_INDEXER_ENABLED=false
-SECRET_KEY=${SECRET_KEY}
-EOF
-msg_ok "Configured Environment"
-
-msg_info "Building AFFiNE (Patience)"
-cd /opt/affine
-source /root/.profile
-export PATH="/root/.cargo/bin:$PATH"
-export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
-export VITE_CORE_COMMIT_SHA=$(cat ~/.affine_app)
-# # Initialize git repo (required for build process)
-export HUSKY=0
-$STD git init -q
-$STD git config user.email "build@local"
-$STD git config user.name "Build"
-$STD git add -A
-$STD git commit -q -m "update" --no-verify --allow-empty
-mkdir -p /opt/affine/.turbo
-cat </opt/affine/.turbo/config.json
-{
- "concurrency": 1
-}
-TURBO
-$STD corepack enable
-$STD corepack prepare yarn@4.13.0 --activate
-$STD yarn config set enableTelemetry 0
-export NODE_OPTIONS="--max-old-space-size=4096"
-export TSC_COMPILE_ON_ERROR=true
-$STD yarn install
-$STD npm install -g typescript
-$STD yarn affine @affine/native build
-$STD yarn affine @affine/server-native build
-
-# Create architecture-specific symlinks for server-native
-ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.x64.node
-ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.arm64.node
-ln -sf /opt/affine/packages/backend/native/server-native.node \
- /opt/affine/packages/backend/native/server-native.armv7.node
-
-$STD yarn affine init
-$STD yarn affine build -p @affine/reader
-$STD yarn affine build -p @affine/server
-export NODE_OPTIONS="--max-old-space-size=4096"
-$STD yarn affine build -p @affine/web
-$STD yarn affine build -p @affine/admin
-mkdir -p /opt/affine/packages/backend/server/static
-cp -r /opt/affine/packages/frontend/apps/web/dist/* /opt/affine/packages/backend/server/static/
-mkdir -p /opt/affine/packages/backend/server/static/admin
-cp -r /opt/affine/packages/frontend/admin/dist/* /opt/affine/packages/backend/server/static/admin/
-# Create empty mobile manifest (server expects it but we don't build mobile)
-mkdir -p /opt/affine/packages/backend/server/static/mobile
-cat <<'MANIFEST' >/opt/affine/packages/backend/server/static/mobile/assets-manifest.json
-{"publicPath":"/","js":[],"css":[],"gitHash":"","description":""}
-MANIFEST
-msg_ok "Built AFFiNE"
-
-msg_info "Running Initial Migration"
-cd /opt/affine/packages/backend/server
-set -a && source /opt/affine/.env && set +a
-$STD node ./scripts/self-host-predeploy.js
-msg_ok "Ran Initial Migration"
-
-msg_info "Creating Services"
-cat </etc/systemd/system/affine-web.service
-[Unit]
-Description=AFFiNE Web Server
-After=network.target postgresql.service redis-server.service
-Requires=postgresql.service redis-server.service
-
-[Service]
-Type=simple
-WorkingDirectory=/opt/affine/packages/backend/server
-EnvironmentFile=/opt/affine/.env
-Environment=LD_PRELOAD=libjemalloc.so.2
-Environment=NODE_OPTIONS=--max-old-space-size=1024
-ExecStart=/usr/bin/node ./dist/main.js
-Restart=always
-RestartSec=10
-
-[Install]
-WantedBy=multi-user.target
-EOF
-
-cat </etc/systemd/system/affine-worker.service
-[Unit]
-Description=AFFiNE Background Worker
-After=network.target postgresql.service redis-server.service
-Requires=postgresql.service redis-server.service
-
-[Service]
-Type=simple
-WorkingDirectory=/opt/affine/packages/backend/server
-EnvironmentFile=/opt/affine/.env
-Environment=LD_PRELOAD=libjemalloc.so.2
-Environment=NODE_OPTIONS=--max-old-space-size=1024
-ExecStart=/usr/bin/node ./dist/main.js --worker
-Restart=always
-RestartSec=10
-
-[Install]
-WantedBy=multi-user.target
-EOF
-
-systemctl enable -q --now redis-server affine-web affine-worker
-msg_ok "Created Services"
-
-msg_info "Creating Admin User"
-ADMIN_PASS=$(openssl rand -base64 12)
-for i in {1..30}; do
- if curl -s http://localhost:3010/info >/dev/null 2>&1; then
- break
- fi
- sleep 2
-done
-# Create admin via API
-ADMIN_RESPONSE=$(curl -s -X POST http://localhost:3010/api/setup/create-admin-user \
- -H "Content-Type: application/json" \
- -d "{\"email\":\"admin@affine.local\",\"password\":\"${ADMIN_PASS}\"}")
-if echo "$ADMIN_RESPONSE" | grep -q '"id"'; then
- {
- echo "AFFiNE Credentials"
- echo "=================="
- echo "Email: admin@affine.local"
- echo "Password: ${ADMIN_PASS}"
- } >~/affine.creds
- msg_ok "Created Admin User"
-else
- msg_warn "Admin creation skipped (may already exist)"
-fi
-
-msg_info "Configuring Nginx"
-cat </etc/nginx/sites-available/affine.conf
-upstream affine_backend {
- server 127.0.0.1:3010;
-}
-
-server {
- listen 80;
- server_name _;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://affine_backend;
- proxy_http_version 1.1;
- proxy_set_header Host \$host;
- proxy_set_header X-Real-IP \$remote_addr;
- proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto \$scheme;
- proxy_set_header Upgrade \$http_upgrade;
- proxy_set_header Connection "upgrade";
- proxy_redirect off;
- proxy_buffering off;
- }
-}
-EOF
-ln -sf /etc/nginx/sites-available/affine.conf /etc/nginx/sites-enabled/
-rm -f /etc/nginx/sites-enabled/default
-systemctl enable -q --now nginx
-msg_ok "Configured Nginx"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/authentik-install.sh b/install/authentik-install.sh
index 02f89c922..13e4fbe3d 100644
--- a/install/authentik-install.sh
+++ b/install/authentik-install.sh
@@ -54,12 +54,12 @@ NODE_VERSION="24" setup_nodejs
setup_yq
setup_go
RUST_PROFILE="minimal" RUST_TOOLCHAIN="stable" setup_rust
-UV_PYTHON_INSTALL_DIR="/usr/local/bin" PYTHON_VERSION="3.14.6" setup_uv
+UV_PYTHON_INSTALL_DIR="/usr/local/bin" PYTHON_VERSION="3.14.3" setup_uv
PG_VERSION="17" setup_postgresql
PG_DB_NAME="authentik" PG_DB_USER="authentik" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
-XMLSEC_VERSION="1.3.12"
-AUTHENTIK_VERSION="version/2026.5.5"
+XMLSEC_VERSION="1.3.11"
+AUTHENTIK_VERSION="version/2026.5.3"
fetch_and_deploy_gh_release "xmlsec" "lsh123/xmlsec" "tarball" "${XMLSEC_VERSION}" "/opt/xmlsec"
fetch_and_deploy_gh_release "authentik" "goauthentik/authentik" "tarball" "${AUTHENTIK_VERSION}" "/opt/authentik"
fetch_and_deploy_gh_release "geoipupdate" "maxmind/geoipupdate" "binary"
diff --git a/install/beaverhabits-install.sh b/install/beaverhabits-install.sh
deleted file mode 100644
index f58f4003a..000000000
--- a/install/beaverhabits-install.sh
+++ /dev/null
@@ -1,53 +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/daya0576/beaverhabits
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-PYTHON_VERSION="3.14" setup_uv
-
-fetch_and_deploy_gh_release "beaverhabits" "daya0576/beaverhabits" "tarball"
-
-msg_info "Installing Dependencies"
-cd /opt/beaverhabits
-$STD uv sync --no-dev
-msg_ok "Installed Dependencies"
-
-msg_info "Configuring BeaverHabits"
-mkdir -p /opt/beaverhabits/.user
-msg_ok "Configured BeaverHabits"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/beaverhabits.service
-[Unit]
-Description=BeaverHabits Habit Tracker
-After=network.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/beaverhabits
-Environment=HABITS_STORAGE=USER_DISK
-Environment=NICEGUI_STORAGE_PATH=/opt/beaverhabits/.user/.nicegui
-ExecStart=/opt/beaverhabits/.venv/bin/gunicorn beaverhabits.main:app --bind 0.0.0.0:8080 -w 1 -k uvicorn_worker.UvicornWorker --max-requests 10000 --log-level info
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now beaverhabits
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/birdnet-go-install.sh b/install/birdnet-go-install.sh
index df0a96058..b3dfcab8e 100644
--- a/install/birdnet-go-install.sh
+++ b/install/birdnet-go-install.sh
@@ -21,7 +21,7 @@ $STD apt install -y \
ffmpeg
msg_ok "Installed Dependencies"
-fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-$(arch_resolve)*.tar.gz"
+fetch_and_deploy_gh_release "birdnet" "tphakala/birdnet-go" "prebuild" "latest" "/opt/birdnet" "birdnet-go-linux-$(arch_resolve).tar.gz"
msg_info "Setting up BirdNET-Go"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
diff --git a/install/docuseal-install.sh b/install/docuseal-install.sh
index e502256e3..82c89bfc6 100644
--- a/install/docuseal-install.sh
+++ b/install/docuseal-install.sh
@@ -23,8 +23,6 @@ $STD apt install -y \
libreadline-dev \
zlib1g-dev \
libffi-dev \
- libleptonica-dev \
- libleptonica6 \
libvips42 \
libvips-dev \
libheif1 \
diff --git a/install/esphome-install.sh b/install/esphome-install.sh
index 02c46b155..1b5b7367d 100644
--- a/install/esphome-install.sh
+++ b/install/esphome-install.sh
@@ -14,8 +14,7 @@ network_check
update_os
msg_info "Installing Dependencies"
-$STD apt install -y git \
- libusb-1.0-0
+$STD apt install -y git
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv
diff --git a/install/fileflows-install.sh b/install/fileflows-install.sh
index 14efb6582..af93424b6 100644
--- a/install/fileflows-install.sh
+++ b/install/fileflows-install.sh
@@ -26,8 +26,8 @@ msg_info "Installing ASP.NET Core Runtime"
if [[ "$(arch_resolve)" == "arm64" ]]; then
# packages.microsoft.com only ships amd64 debs for Debian; use dotnet-install on arm64
curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
- $STD bash /tmp/dotnet-install.sh --channel 10.0 --runtime aspnetcore --install-dir /usr/lib/dotnet10
- ln -sf /usr/lib/dotnet10/dotnet /usr/bin/dotnet
+ $STD bash /tmp/dotnet-install.sh --channel 8.0 --runtime aspnetcore --install-dir /usr/lib/dotnet8
+ ln -sf /usr/lib/dotnet8/dotnet /usr/bin/dotnet
rm -f /tmp/dotnet-install.sh
else
setup_deb822_repo \
@@ -35,7 +35,7 @@ else
"https://packages.microsoft.com/keys/microsoft-2025.asc" \
"https://packages.microsoft.com/debian/13/prod/" \
"trixie"
- $STD apt install -y aspnetcore-runtime-10.0
+ $STD apt install -y aspnetcore-runtime-8.0
fi
msg_ok "Installed ASP.NET Core Runtime"
@@ -55,12 +55,9 @@ if [[ "$install_server" =~ ^[Ss]$ ]]; then
msg_ok "Installed FileFlows Server"
else
msg_info "Installing FileFlows Node"
- read -r -p "${TAB3}Enter FileFlows Server URL (e.g. http://192.168.1.10:19200): " server_url
- while [[ -z "${server_url// /}" ]]; do
- read -r -p "${TAB3}Enter FileFlows Server URL (e.g. http://192.168.1.10:19200): " server_url
- done
cd /opt/fileflows/Node
- $STD dotnet FileFlows.Node.dll --server "$server_url" --systemd install --root true
+ $STD dotnet FileFlows.Node.dll
+ $STD dotnet FileFlows.Node.dll --systemd install --root true
systemctl enable -q --now fileflows-node
msg_ok "Installed FileFlows Node"
fi
diff --git a/install/fireshare-install.sh b/install/fireshare-install.sh
index 311ba230b..982679c6e 100644
--- a/install/fireshare-install.sh
+++ b/install/fireshare-install.sh
@@ -141,9 +141,6 @@ cp /opt/fireshare/app/nginx/prod.conf /etc/nginx/nginx.conf
sed -i 's|root /processed/|root /opt/fireshare-processed/|g' /etc/nginx/nginx.conf
sed -i 's/^user[[:space:]]\+nginx;/user root;/' /etc/nginx/nginx.conf
sed -i 's|root[[:space:]]\+/app/build;|root /opt/fireshare/app/client/build;|' /etc/nginx/nginx.conf
-sed -i 's/__FIRESHARE_PORT__/80/g' /etc/nginx/nginx.conf
-cp /opt/fireshare/app/nginx/error.html /etc/nginx/
-cp /opt/fireshare/app/nginx/api_unavailable.html /etc/nginx/
systemctl start nginx
cat <~/fireshare.creds
diff --git a/install/grav-install.sh b/install/grav-install.sh
deleted file mode 100644
index 8b3c396cf..000000000
--- a/install/grav-install.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: Raffaele (rafspiny)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://getgrav.org/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y \
- nginx \
- logrotate
-msg_ok "Installed Dependencies"
-
-PHP_FPM="YES" setup_php
-
-fetch_and_deploy_gh_release "grav" "getgrav/grav" "prebuild" "latest" "/opt/grav" "grav-admin-v*zip"
-chown -R www-data:www-data /opt/grav
-
-msg_info "Configuring Nginx"
-PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')
-PHP_FPM_SOCK=$(find /run/php -maxdepth 1 -name "php*-fpm.sock" -type s | sort -V | tail -1)
-unlink /etc/nginx/sites-enabled/default
-rm -f /etc/nginx/sites-available/default
-cat </etc/nginx/sites-available/grav
-server {
- listen 80;
- server_name _;
- root /opt/grav;
- index index.html index.htm index.php;
-
- location / {
- try_files \$uri \$uri/ /index.html /index.htm /index.php\$is_args\$args;
- }
-
- ## Begin - Security
- location ~* /(\.git|cache|bin|logs|backup|tests)/.*$ { return 403; }
- location ~* /(system|vendor)/.*\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
- location ~* /user/.*\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
- location ~ /(LICENSE\.txt|composer\.lock|composer\.json|nginx\.conf|web\.config|htaccess\.txt|\.htaccess) { return 403; }
- ## End - Security
-
- ## Begin - API
- location ^~ /api/ {
- try_files \$uri \$uri/ /index.php\$is_args\$args;
- }
- ## End - API
-
- # deny all direct access to these sensitive user folders, whatever the file type
- location ~* /user/(accounts|config|env)/.*$ { return 403; }
- # allow public media uploads under user/data to be served directly;
- # this must come before the user/data deny so it wins the match
- location ~* /user/data/.*\.(jpe?g|png|gif|webp|avif|bmp|ico|mp4|webm|ogg|ogv|mov|mp3|wav|m4a|flac|pdf)$ { try_files \$uri =404; }
- # deny everything else under user/data
- location ~* /user/data/.*$ { return 403; }
-
-
- ## Begin - Caching
- location ~* ^/forms-basic-captcha-image.jpg$ {
- try_files \$uri \$uri/ /index.php\$is_args\$args;
- }
-
- location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
- expires 30d;
- add_header Vary Accept-Encoding;
- log_not_found off;
- }
-
- location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ {
- access_log off;
- expires 30d;
- add_header Cache-Control public;
- tcp_nodelay off;
- open_file_cache max=3000 inactive=120s;
- open_file_cache_valid 45s;
- open_file_cache_min_uses 2;
- open_file_cache_errors off;
- }
- ## End - Caching
-
- location ~ ^(.+\.php)(.*)$ {
- fastcgi_split_path_info ^(.+\.php)(.*)$;
- if (!-f \$document_root\$fastcgi_script_name) { return 404; }
- fastcgi_pass unix:${PHP_FPM_SOCK};
- fastcgi_index index.php;
- include /etc/nginx/fastcgi_params;
- fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
- }
-
- location ~ /\.ht {
- deny all;
- }
-}
-EOF
-ln -sf /etc/nginx/sites-available/grav /etc/nginx/sites-enabled/grav
-systemctl enable -q --now php${PHP_VER}-fpm
-$STD nginx -t
-systemctl enable -q --now nginx
-$STD nginx -s reload
-msg_ok "Configured Nginx"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/hyperion-install.sh b/install/hyperion-install.sh
index b58798f96..db5bf301f 100644
--- a/install/hyperion-install.sh
+++ b/install/hyperion-install.sh
@@ -24,12 +24,6 @@ msg_ok "Set up Hyperion repository"
msg_info "Installing Hyperion"
$STD apt install -y hyperion
-mkdir -p /etc/systemd/system/hyperion@.service.d
-cat </etc/systemd/system/hyperion@.service.d/override.conf
-[Unit]
-Requisite=
-EOF
-systemctl daemon-reload
systemctl enable -q --now hyperion@root
msg_ok "Installed Hyperion"
diff --git a/install/immich-install.sh b/install/immich-install.sh
index 688ae657e..fcaad3e0b 100644
--- a/install/immich-install.sh
+++ b/install/immich-install.sh
@@ -162,7 +162,7 @@ PG_VERSION="16" PG_MODULES="pgvector" setup_postgresql
ACTUAL_PG_VERSION=$(ls /etc/postgresql/ 2>/dev/null | sort -V | tail -1)
ACTUAL_PG_VERSION=${ACTUAL_PG_VERSION:-16}
-VCHORD_RELEASE="1.1.1"
+VCHORD_RELEASE="1.0.0"
fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-${ACTUAL_PG_VERSION}-vchord_*_$(arch_resolve).deb"
sed -i "s/^#shared_preload.*/shared_preload_libraries = 'vchord.so'/" /etc/postgresql/${ACTUAL_PG_VERSION}/main/postgresql.conf
@@ -286,7 +286,6 @@ LIBVIPS_REVISION="e01a4797cabe77d457fdfa7d776b7a7e7ca6d6a7"
$STD git clone https://github.com/libvips/libvips.git "$SOURCE"
cd "$SOURCE"
$STD git reset --hard "$LIBVIPS_REVISION"
-$STD git apply "$BASE_DIR"/server/sources/libvips-patches/0001-put-other-loaders-ahead-of-dcrawload.patch
$STD meson setup build --buildtype=release --libdir=lib -Dintrospection=disabled -Dtiff=disabled
cd build
$STD ninja install
@@ -312,7 +311,7 @@ ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
-fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.3" "$SRC_DIR"
+fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.1" "$SRC_DIR"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs
@@ -438,27 +437,6 @@ cd "$INSTALL_DIR"
ln -s "$GEO_DIR" "$APP_DIR"
msg_ok "Installed GeoNames data"
-# MickLesk temporary patch for HEIC thumbnail gen
-msg_info "Patching media.repository.js"
-MEDIA_REPO_JS="/opt/immich/app/dist/repositories/media.repository.js"
-if [[ -f "$MEDIA_REPO_JS" ]]; then
- python3 - <<'PY'
-from pathlib import Path
-p = Path('/opt/immich/app/dist/repositories/media.repository.js')
-s = p.read_text()
-old = "(0, sharp_1.default)(input).metadata()"
-new = "(0, sharp_1.default)(input, { unlimited: true, limitInputPixels: false }).metadata()"
-if new in s:
- print('hotfix already there')
-elif old in s:
- p.write_text(s.replace(old, new, 1))
- print('hotfix applied')
-else:
- print('pattern not found, skipped')
-PY
-fi
-msg_ok "Patched media.repository.js"
-
mkdir -p /var/log/immich
touch /var/log/immich/{web.log,ml.log}
msg_ok "Installed Immich"
diff --git a/install/invidious-install.sh b/install/invidious-install.sh
deleted file mode 100644
index 798b09e92..000000000
--- a/install/invidious-install.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: vhsdream
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/iv-org/invidious
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y \
- build-essential \
- git \
- pkg-config \
- libssl-dev \
- libxml2-dev \
- libyaml-dev \
- libgmp-dev \
- libreadline-dev \
- librsvg2-bin \
- libsqlite3-dev \
- zlib1g-dev \
- libpcre2-dev \
- libevent-dev \
- fonts-open-sans
-msg_ok "Installed Dependencies"
-
-if [[ "$(arch_resolve amd64 arm64)" == "amd64" ]]; then
- setup_deb822_repo "crystal" "https://download.opensuse.org/repositories/devel:/languages:/crystal/Debian_13/Release.key" "https://download.opensuse.org/repositories/devel:/languages:/crystal/Debian_13/" "./"
- $STD apt install -y crystal
-else
- fetch_and_deploy_gh_release "Crystal" "crystal-lang/crystal" "prebuild" "latest" "/opt/crystal" "crystal-*-linux-aarch64-bundled.tar.gz"
- ln -sf /opt/crystal/bin/crystal /usr/local/bin/crystal
- ln -sf /opt/crystal/bin/shards /usr/local/bin/shards
-fi
-
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="invidious" PG_DB_USER="invidious" setup_postgresql_db
-fetch_and_deploy_gh_release "Invidious" "iv-org/invidious" "tarball" "latest" "/opt/invidious"
-fetch_and_deploy_gh_release "Invidious Companion" "iv-org/invidious-companion" "prebuild" "latest" "/opt/invidious-companion" "invidious_companion-$(arch_resolve x86_64 aarch64)-unknown-linux-gnu.tar.gz"
-
-msg_info "Building Invidious"
-cd /opt/invidious
-INVIDIOUS_VERSION="$(cat ~/.invidious 2>/dev/null || echo "unknown")"
-INVIDIOUS_VERSION="${INVIDIOUS_VERSION#v}"
-sed -i \
- -e "s~^\(\s*CURRENT_BRANCH\s*=\).*~\1 \"master\"~" \
- -e "s~^\(\s*CURRENT_COMMIT\s*=\).*~\1 \"\"~" \
- -e "s~^\(\s*CURRENT_VERSION\s*=\).*~\1 \"${INVIDIOUS_VERSION}\"~" \
- -e "s~^\(\s*CURRENT_TAG\s*=\).*~\1 \"${INVIDIOUS_VERSION}\"~" \
- -e "s~^\(\s*ASSET_COMMIT\s*=\).*~\1 \"\"~" \
- src/invidious.cr
-$STD make
-msg_ok "Built Invidious"
-
-msg_info "Configuring Invidious"
-SECRET_KEY="$(openssl rand -hex 8)"
-HMAC_KEY="$(openssl rand -hex 32)"
-sed -e '\~^db:~,\~dbname:~d' \
- -e "s~^#database_.*~database_url: postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}~" \
- -e 's~^#check_tables.*~check_tables: true~' \
- -e 's~^#invidious_companion:~invidious_companion:~' \
- -e 's~^# - private_~ - private_~' \
- -e "s~^#invidious_companion_key:.*~invidious_companion_key: \"${SECRET_KEY}\"~" \
- -e "s~^hmac_key:.*~hmac_key: \"${HMAC_KEY}\"~" \
- /opt/invidious/config/config.example.yml >/opt/invidious/config/config.yml
-chmod 600 /opt/invidious/config/config.yml
-
-cat </etc/logrotate.d/invidious.logrotate
-/opt/invidious/invidious.log {
- rotate 4
- weekly
- notifempty
- missingok
- compress
- minsize 1048576
-}
-EOF
-chmod 0644 /etc/logrotate.d/invidious.logrotate
-msg_ok "Configured Invidious"
-
-msg_info "Migrating database"
-$STD ./invidious --migrate
-msg_ok "Migrated database"
-
-msg_info "Configuring services"
-sed -e 's|^User=invidious|User=root|' \
- -e 's|^Group=invidious|Group=root|' \
- -e 's|/home/invidious/invidious|/opt/invidious|g' \
- /opt/invidious/invidious.service >/etc/systemd/system/invidious.service
-mkdir -p /var/tmp/youtubei.js
-cat </etc/systemd/system/invidious-companion.service
-[Unit]
-Description=Invidious Companion
-After=network.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/invidious-companion
-Environment=SERVER_SECRET_KEY=${SECRET_KEY}
-Environment=CACHE_DIRECTORY=/var/tmp/youtubei.js
-ExecStart=/opt/invidious-companion/invidious_companion
-Restart=always
-RestartSec=2s
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl -q enable --now invidious invidious-companion
-msg_ok "Configured services"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/leafwiki-install.sh b/install/leafwiki-install.sh
deleted file mode 100644
index 228ffc702..000000000
--- a/install/leafwiki-install.sh
+++ /dev/null
@@ -1,55 +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/perber/leafwiki
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-fetch_and_deploy_gh_release "leafwiki" "perber/leafwiki" "singlefile" "latest" "/usr/local/bin" "leafwiki-v*-linux-$(arch_resolve)"
-
-msg_info "Configuring LeafWiki"
-mkdir -p /opt/leafwiki/data
-mkdir -p /etc/leafwiki
-JWT_SECRET=$(openssl rand -hex 32)
-ADMIN_PASS=$(openssl rand -base64 12 | tr -dc 'a-zA-Z0-9' | head -c12)
-cat </etc/leafwiki/.env
-LEAFWIKI_DATA_DIR=/opt/leafwiki/data
-LEAFWIKI_HOST=0.0.0.0
-LEAFWIKI_PORT=8080
-LEAFWIKI_JWT_SECRET=${JWT_SECRET}
-LEAFWIKI_ADMIN_PASSWORD=${ADMIN_PASS}
-LEAFWIKI_ALLOW_INSECURE=true
-EOF
-msg_ok "Configured LeafWiki"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/leafwiki.service
-[Unit]
-Description=LeafWiki
-After=network.target
-
-[Service]
-Type=simple
-User=root
-EnvironmentFile=/etc/leafwiki/.env
-ExecStart=/usr/local/bin/leafwiki
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now leafwiki
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/localagi-install.sh b/install/localagi-install.sh
deleted file mode 100644
index 3589d1b8b..000000000
--- a/install/localagi-install.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: BillyOutlast
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/mudler/LocalAGI
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-APP="LocalAGI"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y build-essential
-msg_ok "Installed Dependencies"
-
-NODE_VERSION="24" setup_nodejs
-setup_go
-
-msg_info "Installing Bun"
-export BUN_INSTALL="/root/.bun"
-curl -fsSL https://bun.sh/install | $STD bash
-ln -sf /root/.bun/bin/bun /usr/local/bin/bun
-ln -sf /root/.bun/bin/bunx /usr/local/bin/bunx
-msg_ok "Installed Bun"
-
-fetch_and_deploy_gh_release "localagi" "mudler/LocalAGI" "tarball" "latest" "/opt/localagi"
-
-msg_info "Configuring LocalAGI"
-mkdir -p /opt/localagi/pool
-cat <<'EOF' >/opt/localagi/.env
-LOCALAGI_MODEL=gemma-3-4b-it-qat
-LOCALAGI_MULTIMODAL_MODEL=moondream2-20250414
-LOCALAGI_IMAGE_MODEL=sd-1.5-ggml
-LOCALAGI_LLM_API_URL=http://127.0.0.1:11434/v1
-LOCALAGI_STATE_DIR=/opt/localagi/pool
-EOF
-msg_ok "Configured LocalAGI"
-
-msg_info "Setting up LocalAGI"
-cd /opt/localagi/webui/react-ui
-$STD bun install
-$STD bun run build
-cd /opt/localagi
-$STD go build -o /usr/local/bin/localagi
-msg_ok "Set up LocalAGI"
-
-msg_info "Creating LocalAGI systemd service"
-cat </etc/systemd/system/localagi.service
-[Unit]
-Description=LocalAGI
-After=network.target
-
-[Service]
-User=root
-Type=simple
-EnvironmentFile=/opt/localagi/.env
-
-WorkingDirectory=/opt/localagi
-ExecStart=/usr/local/bin/localagi
-Restart=on-failure
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now localagi
-msg_ok "Created LocalAGI systemd service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/manyfold-install.sh b/install/manyfold-install.sh
index 0a025b1cf..dfc43b49e 100644
--- a/install/manyfold-install.sh
+++ b/install/manyfold-install.sh
@@ -31,14 +31,13 @@ NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold/app"
-useradd -m -s /usr/bin/bash manyfold
-
RUBY_INSTALL_VERSION=$(cat /opt/manyfold/app/.ruby-version)
RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" HOME=/home/manyfold setup_ruby
msg_info "Configuring Manyfold"
YARN_VERSION=$(grep '"packageManager":' /opt/manyfold/app/package.json | sed -E 's/.*"(yarn@[0-9\.]+)".*/\1/')
RELEASE=$(get_latest_github_release "manyfold3d/manyfold")
+useradd -m -s /usr/bin/bash manyfold
cat </opt/manyfold/.env
export APP_VERSION=${RELEASE}
export GUID=1002
diff --git a/install/n8n-install.sh b/install/n8n-install.sh
index c6f0d421a..8ddf37d0b 100644
--- a/install/n8n-install.sh
+++ b/install/n8n-install.sh
@@ -16,6 +16,7 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
build-essential \
+ python3 \
python3-setuptools \
graphicsmagick
msg_ok "Installed Dependencies"
@@ -23,7 +24,7 @@ msg_ok "Installed Dependencies"
NODE_VERSION="24" setup_nodejs
msg_info "Installing n8n (Patience)"
-$STD npm install -g n8n@latest
+$STD npm install -g n8n@2.27.5
msg_ok "Installed n8n"
msg_info "Creating Service"
diff --git a/install/nexterm-install.sh b/install/nexterm-install.sh
deleted file mode 100644
index 1ef0ecfe8..000000000
--- a/install/nexterm-install.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: Mathias Wagner (gnmyt)
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://nexterm.dev/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-fetch_and_deploy_gh_release "nexterm-engine" "gnmyt/Nexterm" "prebuild" "latest" "/opt/nexterm/engine" "nexterm-engine-linux-$(arch_resolve "x64" "arm64").tar.gz"
-fetch_and_deploy_gh_release "nexterm-server" "gnmyt/Nexterm" "singlefile" "latest" "/opt/nexterm/server" "nexterm-server-linux-$(arch_resolve "x64" "arm64")"
-
-msg_info "Configuring Nexterm"
-LOCAL_ENGINE_TOKEN=$(tr -d '-' /etc/nexterm-engine/config.yaml
-server_host: "127.0.0.1"
-server_port: 7800
-registration_token: "${LOCAL_ENGINE_TOKEN}"
-tls: false
-EOF
-cat </etc/nexterm-server/server.env
-NODE_ENV=production
-SERVER_PORT=6989
-LOCAL_ENGINE_TOKEN=${LOCAL_ENGINE_TOKEN}
-ENCRYPTION_KEY=${ENCRYPTION_KEY}
-EOF
-chmod 0640 /etc/nexterm-engine/config.yaml /etc/nexterm-server/server.env
-msg_ok "Configured Nexterm"
-
-msg_info "Creating Services"
-cat </etc/systemd/system/nexterm-server.service
-[Unit]
-Description=Nexterm Server
-Documentation=https://docs.nexterm.dev/
-After=network-online.target
-Wants=network-online.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/nexterm/data
-EnvironmentFile=/etc/nexterm-server/server.env
-ExecStart=/opt/nexterm/server/nexterm-server
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-cat </etc/systemd/system/nexterm-engine.service
-[Unit]
-Description=Nexterm Engine
-Documentation=https://docs.nexterm.dev/
-After=network-online.target nexterm-server.service
-Wants=network-online.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/etc/nexterm-engine
-Environment=FREERDP_EXTENSION_PATH=/opt/nexterm/engine/lib/freerdp2
-Environment=LD_LIBRARY_PATH=/opt/nexterm/engine/lib
-ExecStart=/opt/nexterm/engine/nexterm-engine
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now nexterm-server
-sleep 5
-systemctl enable -q --now nexterm-engine
-msg_ok "Created Services"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/notediscovery-install.sh b/install/notediscovery-install.sh
deleted file mode 100644
index 26687f8c6..000000000
--- a/install/notediscovery-install.sh
+++ /dev/null
@@ -1,51 +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/gamosoft/NoteDiscovery
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-setup_uv
-
-fetch_and_deploy_gh_release "notediscovery" "gamosoft/NoteDiscovery" "tarball"
-
-msg_info "Installing Dependencies"
-cd /opt/notediscovery
-$STD uv sync --no-dev
-msg_ok "Installed Dependencies"
-
-msg_info "Configuring NoteDiscovery"
-mkdir -p /opt/notediscovery/data
-msg_ok "Configured NoteDiscovery"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/notediscovery.service
-[Unit]
-Description=NoteDiscovery Knowledge Base
-After=network.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/notediscovery
-ExecStart=/opt/notediscovery/.venv/bin/python /opt/notediscovery/run.py
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now notediscovery
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/opencloud-install.sh b/install/opencloud-install.sh
index d0cb26994..608440062 100644
--- a/install/opencloud-install.sh
+++ b/install/opencloud-install.sh
@@ -64,7 +64,7 @@ $STD sudo -u cool coolconfig set-admin-password --user=admin --password="$COOLPA
echo "$COOLPASS" >~/.coolpass
msg_ok "Installed Collabora Online"
-fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.3.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
+fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.2.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
mv /usr/bin/OpenCloud /usr/bin/opencloud
msg_info "Configuring OpenCloud"
diff --git a/install/oxicloud-install.sh b/install/oxicloud-install.sh
deleted file mode 100644
index 1b80f103c..000000000
--- a/install/oxicloud-install.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: vhsdream
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://github.com/DioCrafts/OxiCloud
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Installing Dependencies"
-$STD apt install -y build-essential
-msg_ok "Installed Dependencies"
-
-NODE_VERSION="24" setup_nodejs
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="oxicloud" PG_DB_USER="oxicloud" setup_postgresql_db
-fetch_and_deploy_gh_release "OxiCloud" "DioCrafts/OxiCloud" "tarball" "latest" "/opt/oxicloud"
-TOOLCHAIN="$(grep -oP 'FROM\s+rust:\K[0-9]+\.[0-9]+(\.[0-9]+)?' /opt/oxicloud/Dockerfile | head -1)"
-RUST_TOOLCHAIN="${TOOLCHAIN:-stable}" setup_rust
-
-msg_info "Building Frontend SPA"
-cd /opt/oxicloud/frontend
-$STD npm ci
-$STD npm run build
-msg_ok "Built Frontend SPA"
-
-msg_info "Building OxiCloud (Patience)"
-cd /opt/oxicloud
-export DATABASE_URL="postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost/${PG_DB_NAME}"
-export RUSTFLAGS="-C target-cpu=native"
-RAM_MB=$(awk '/MemTotal/ {print int($2/1024)}' /proc/meminfo)
-CARGO_JOBS=$((RAM_MB / 2560))
-[[ $CARGO_JOBS -lt 1 ]] && CARGO_JOBS=1
-[[ $CARGO_JOBS -gt $(nproc) ]] && CARGO_JOBS=$(nproc)
-$STD cargo build --release -j "$CARGO_JOBS" --bin oxicloud --bin migrate-nfc-filenames
-mv target/release/oxicloud /usr/local/bin/oxicloud
-mv target/release/migrate-nfc-filenames /usr/local/bin/migrate-nfc-filenames
-rm -rf /opt/oxicloud/static
-mv /opt/oxicloud/static-dist /opt/oxicloud/static
-rm -rf /opt/oxicloud/target /opt/oxicloud/frontend/node_modules
-msg_ok "Built OxiCloud"
-
-msg_info "Configuring OxiCloud"
-mkdir -p {/mnt/oxicloud,/etc/oxicloud}
-sed -e 's|OXICLOUD_STORAGE_PATH=.*|OXICLOUD_STORAGE_PATH=/mnt/oxicloud|' \
- -e 's|OXICLOUD_SERVER_HOST=.*|OXICLOUD_SERVER_HOST=0.0.0.0|' \
- -e 's|OXICLOUD_STATIC_PATH=.*|OXICLOUD_STATIC_PATH=/opt/oxicloud/static|' \
- -e "s|^#OXICLOUD_BASE_URL=.*|OXICLOUD_BASE_URL=http://${LOCAL_IP}:8086|" \
- -e "s|OXICLOUD_DB_CONNECTION_STRING=.*|OXICLOUD_DB_CONNECTION_STRING=${DATABASE_URL}|" \
- -e "s|^DATABASE_URL=.*|DATABASE_URL=${DATABASE_URL}|" \
- -e "s|^#OXICLOUD_JWT_SECRET=.*|OXICLOUD_JWT_SECRET=$(openssl rand -hex 32)|" \
- /opt/oxicloud/example.env >/etc/oxicloud/.env
-chmod 600 /etc/oxicloud/.env
-msg_ok "Configured OxiCloud"
-
-msg_info "Creating OxiCloud Service"
-cat </etc/systemd/system/oxicloud.service
-[Unit]
-Description=OxiCloud Service
-After=network.target postgresql.service
-Requires=postgresql.service
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/oxicloud
-EnvironmentFile=/etc/oxicloud/.env
-ExecStart=/usr/local/bin/oxicloud
-Restart=always
-RestartSec=5
-StandardOutput=journal
-StandardError=journal
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now oxicloud
-msg_ok "Created OxiCloud Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/pangolin-install.sh b/install/pangolin-install.sh
index 0a8f008af..ab3fc5095 100644
--- a/install/pangolin-install.sh
+++ b/install/pangolin-install.sh
@@ -16,19 +16,18 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
build-essential \
+ python3 \
+ sqlite3 \
iptables
msg_ok "Installed Dependencies"
NODE_VERSION="24" setup_nodejs
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="pangolin" PG_DB_USER="pangolin" setup_postgresql_db
-PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.20.0}"
+PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.4}"
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION"
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_$(arch_resolve)"
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_$(arch_resolve).tar.gz"
read -rp "${TAB3}Enter your Pangolin URL (ex: https://pangolin.example.com): " pango_url
-[[ "$pango_url" != https://* && "$pango_url" != http://* ]] && pango_url="https://${pango_url}"
read -rp "${TAB3}Enter your email address: " pango_email
msg_info "Setup Pangolin"
@@ -37,14 +36,13 @@ BADGER_VERSION=$(get_latest_github_release "fosrl/badger" "false")
cd /opt/pangolin
mkdir -p /opt/pangolin/config/{traefik,db,letsencrypt,logs}
$STD npm ci
-$STD npm run set:pg
+$STD npm run set:sqlite
$STD npm run set:oss
rm -rf server/private
-DATABASE_URL="postgresql://pangolin:${PG_DB_PASS}@localhost:5432/pangolin" $STD npm run db:generate
+$STD npm run db:generate
$STD npm run build
$STD npm run build:cli
cp -R .next/standalone ./
-cp -r server/migrations ./dist/init
cat </usr/local/bin/pangctl
#!/bin/sh
@@ -76,9 +74,6 @@ flags:
require_email_verification: false
disable_signup_without_invite: false
disable_user_create_org: false
-
-postgres:
- connection_string: "postgresql://pangolin:${PG_DB_PASS}@localhost:5432/pangolin"
EOF
cat </opt/pangolin/config/traefik/traefik_config.yml
@@ -186,8 +181,7 @@ http:
servers:
- url: "http://$LOCAL_IP:3000"
EOF
-export ENVIRONMENT=prod
-$STD node dist/migrations.mjs
+$STD npm run db:push
. /etc/os-release
if [ "$VERSION_CODENAME" = "trixie" ]; then
@@ -203,8 +197,7 @@ msg_info "Creating Services"
cat </etc/systemd/system/pangolin.service
[Unit]
Description=Pangolin Service
-After=network.target postgresql.service
-Wants=postgresql.service
+After=network.target
[Service]
Type=simple
diff --git a/install/pihole-install.sh b/install/pihole-install.sh
index 547d79f23..c88a7c997 100644
--- a/install/pihole-install.sh
+++ b/install/pihole-install.sh
@@ -119,8 +119,7 @@ edns-packet-max=1232
EOF
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
- cat <>/etc/unbound/unbound.conf.d/pi-hole.conf
-server:
+ cat </etc/unbound/unbound.conf.d/pi-hole.conf
tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
forward-zone:
name: "."
diff --git a/install/pocketid-install.sh b/install/pocketid-install.sh
index 11b8fa591..47f945d3b 100644
--- a/install/pocketid-install.sh
+++ b/install/pocketid-install.sh
@@ -14,7 +14,7 @@ network_check
update_os
read -r -p "${TAB3}What public URL do you want to use (e.g. pocketid.mydomain.com)? " public_url
-fetch_and_deploy_gh_release "pocket-id" "pocket-id/pocket-id" "singlefile" "latest" "/opt/pocket-id/" "pocket-id_linux_$(arch_resolve)"
+fetch_and_deploy_gh_release "pocket-id" "pocket-id/pocket-id" "singlefile" "latest" "/opt/pocket-id/" "pocket-id-linux-$(arch_resolve)"
msg_info "Configuring Pocket ID"
ENCRYPTION_KEY=$(openssl rand -base64 32)
diff --git a/install/reitti-install.sh b/install/reitti-install.sh
index 512b0cd13..2810b1495 100644
--- a/install/reitti-install.sh
+++ b/install/reitti-install.sh
@@ -30,30 +30,27 @@ mv /opt/reitti/reitti-*.jar /opt/reitti/reitti.jar
msg_info "Installing Nginx Tile Cache"
mkdir -p /var/cache/nginx/tiles
-cat <<'NGINXEOF' >/etc/nginx/nginx.conf
+cat </etc/nginx/nginx.conf
user www-data;
events {
worker_connections 1024;
}
http {
- resolver 1.1.1.1 8.8.8.8 valid=30s ipv6=off;
proxy_cache_path /var/cache/nginx/tiles levels=1:2 keys_zone=tiles:10m max_size=1g inactive=30d use_temp_path=off;
server {
listen 80;
- location /custom/ {
- set $upstream_url $http_x_reitti_upstream_url;
- proxy_pass $upstream_url;
- proxy_set_header Host $proxy_host;
+ location / {
+ proxy_pass https://tile.openstreetmap.org/;
+ proxy_set_header Host tile.openstreetmap.org;
proxy_set_header User-Agent "Reitti/1.0";
proxy_cache tiles;
- proxy_cache_key $upstream_url;
proxy_cache_valid 200 30d;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
}
}
}
-NGINXEOF
+EOF
chown -R www-data:www-data /var/cache/nginx
chmod -R 750 /var/cache/nginx
systemctl restart nginx
@@ -74,7 +71,6 @@ server.compression.mime-types=text/plain,application/json
logging.level.root=INFO
logging.level.org.hibernate.engine.jdbc.spi.SqlExceptionHelper=FATAL
logging.level.com.dedicatedcode.reitti=INFO
-logging.level.org.quartz.core.ErrorLogger=FATAL
# Internationalization
spring.messages.basename=messages
@@ -86,7 +82,7 @@ spring.messages.fallback-to-system-locale=false
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/$PG_DB_NAME
spring.datasource.username=$PG_DB_USER
spring.datasource.password=$PG_DB_PASS
-spring.datasource.hikari.maximum-pool-size=30
+spring.datasource.hikari.maximum-pool-size=20
# Redis configuration
spring.data.redis.host=127.0.0.1
@@ -96,23 +92,20 @@ spring.data.redis.password=
spring.data.redis.database=0
spring.cache.redis.key-prefix=
-spring.cache.cache-names=processed-visits,significant-places,users,magic-links,configurations,transport-mode-configs,avatarThumbnails,avatarData,user-settings,devices,mapStyles,mapStyleJson
+spring.cache.cache-names=processed-visits,significant-places,users,magic-links,configurations,transport-mode-configs,avatarThumbnails,avatarData,user-settings
spring.cache.redis.time-to-live=1d
# Upload configuration
spring.servlet.multipart.max-file-size=5GB
spring.servlet.multipart.max-request-size=5GB
-spring.servlet.multipart.resolve-lazily=true
server.tomcat.max-part-count=100
-spring.mvc.async.request-timeout=600000
-# Quartz Scheduler configuration
-spring.quartz.job-store-type=jdbc
-spring.quartz.jdbc.initialize-schema=never
-spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
-spring.quartz.properties.org.quartz.jobStore.isClustered=false
-spring.quartz.properties.org.quartz.jobStore.tablePrefix=qrtz_
-spring.quartz.properties.org.quartz.threadPool.threadCount=5
+# Rqueue configuration
+rqueue.web.enable=false
+rqueue.job.enabled=false
+rqueue.message.durability.in-terminal-state=0
+rqueue.key.prefix=\${spring.cache.redis.key-prefix}
+rqueue.message.converter.provider.class=com.dedicatedcode.reitti.config.RQueueCustomMessageConverter
# Application-specific settings
reitti.server.advertise-uri=
@@ -124,25 +117,18 @@ reitti.security.oidc.enabled=false
reitti.security.oidc.registration.enabled=false
reitti.import.batch-size=10000
-reitti.import.grace-time-seconds=30
-reitti.import.staging.cleanup.cron=0 0 4 * * *
-
-reitti.batching.max-batch-size=100
-reitti.batching.max-wait-time=5
+reitti.import.processing-idle-start-time=10
reitti.geo-point-filter.max-speed-kmh=1000
reitti.geo-point-filter.max-accuracy-meters=100
reitti.geo-point-filter.history-lookback-hours=24
reitti.geo-point-filter.window-size=50
+reitti.process-data.schedule=0 */10 * * * *
reitti.process-data.refresh-views.schedule=0 0 4 * * *
reitti.imports.schedule=0 5/10 * * * *
reitti.imports.owntracks-recorder.schedule=\${reitti.imports.schedule}
-reitti.jobs.cleanup.cron=0 0 4 * * ?
-reitti.jobs.cleanup.max-age-hours=24
-reitti.db-janitor.schedule=0 0 4 * * ?
-
# Geocoding service configuration
reitti.geocoding.max-errors=10
reitti.geocoding.photon.base-url=
diff --git a/install/sftpgo-install.sh b/install/sftpgo-install.sh
index 5547d2e59..d27d4f761 100644
--- a/install/sftpgo-install.sh
+++ b/install/sftpgo-install.sh
@@ -19,8 +19,8 @@ msg_ok "Installed Dependencies"
setup_deb822_repo \
"sftpgo" \
- "https://oss.sftpgo.com/apt/gpg.key" \
- "https://oss.sftpgo.com/apt" \
+ "https://ftp.osuosl.org/pub/sftpgo/apt/gpg.key" \
+ "https://ftp.osuosl.org/pub/sftpgo/apt" \
"trixie"
msg_info "Installing SFTPGo"
diff --git a/install/shinobi-install.sh b/install/shinobi-install.sh
index 6107c6488..383325016 100644
--- a/install/shinobi-install.sh
+++ b/install/shinobi-install.sh
@@ -54,7 +54,7 @@ cronKey=$(head -c 1024 /etc/systemd/system/silverbullet.service
[Unit]
@@ -36,7 +25,6 @@ After=syslog.target network.target
[Service]
User=root
Type=simple
-${RUNTIME_API_ENV}
ExecStart=/opt/silverbullet/bin/silverbullet --hostname 0.0.0.0 --port 3000 /opt/silverbullet/space
WorkingDirectory=/opt/silverbullet
Restart=on-failure
diff --git a/install/snapotter-install.sh b/install/snapotter-install.sh
index b8330b7ca..7878c441a 100644
--- a/install/snapotter-install.sh
+++ b/install/snapotter-install.sh
@@ -39,19 +39,6 @@ msg_ok "Installed Dependencies"
PYTHON_VERSION="3.11" setup_uv
NODE_VERSION="22" NODE_MODULE="pnpm" setup_nodejs
-PG_VERSION="17" setup_postgresql
-PG_DB_NAME="snapotter" PG_DB_USER="snapotter" setup_postgresql_db
-
-msg_info "Installing Redis"
-$STD apt install -y redis-server
-if grep -q '^appendonly ' /etc/redis/redis.conf; then
- sed -i 's/^appendonly .*/appendonly yes/' /etc/redis/redis.conf
-else
- echo 'appendonly yes' >>/etc/redis/redis.conf
-fi
-$STD systemctl enable --now redis-server
-msg_ok "Installed Redis"
-
fetch_and_deploy_gh_release "caire" "esimov/caire" "prebuild" "latest" "/usr/local/bin" "caire-*-linux-amd64.tar.gz"
fetch_and_deploy_gh_release "snapotter" "snapotter-hq/SnapOtter" "prebuild" "latest" "/opt/snapotter" "snapotter-*-linux-amd64.tar.gz"
@@ -74,8 +61,7 @@ mkdir -p /tmp/snapotter-workspace
cat </opt/snapotter_data/.env
PORT=1349
NODE_ENV=production
-DATABASE_URL=postgres://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
-REDIS_URL=redis://127.0.0.1:6379
+DB_PATH=/opt/snapotter_data/snapotter.db
WORKSPACE_PATH=/tmp/snapotter-workspace
FILES_STORAGE_PATH=/opt/snapotter_data/files
PYTHON_VENV_PATH=/opt/snapotter_data/ai/venv
@@ -99,9 +85,7 @@ PNPM_BIN="$(command -v pnpm)"
cat </etc/systemd/system/snapotter.service
[Unit]
Description=SnapOtter Service
-Wants=network-online.target
-After=network-online.target postgresql.service redis-server.service
-Requires=postgresql.service redis-server.service
+After=network.target
[Service]
Type=simple
@@ -115,7 +99,6 @@ RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
-systemctl daemon-reload
systemctl enable -q --now snapotter
msg_ok "Created Service"
diff --git a/install/squid-install.sh b/install/squid-install.sh
deleted file mode 100644
index aa0110820..000000000
--- a/install/squid-install.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: 007hacky007
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: https://www.squid-cache.org/
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-msg_info "Configuring Squid"
-mkdir -p /etc/squid
-cat </etc/squid/squid.conf
-acl localnet src 0.0.0.1-0.255.255.255
-acl localnet src 10.0.0.0/8
-acl localnet src 100.64.0.0/10
-acl localnet src 169.254.0.0/16
-acl localnet src 172.16.0.0/12
-acl localnet src 192.168.0.0/16
-acl localnet src fc00::/7
-acl localnet src fe80::/10
-
-acl SSL_ports port 443
-acl Safe_ports port 80
-acl Safe_ports port 21
-acl Safe_ports port 443
-acl Safe_ports port 70
-acl Safe_ports port 210
-acl Safe_ports port 1025-65535
-acl Safe_ports port 280
-acl Safe_ports port 488
-acl Safe_ports port 591
-acl Safe_ports port 777
-acl CONNECT method CONNECT
-
-http_access deny !Safe_ports
-http_access deny CONNECT !SSL_ports
-http_access allow localhost manager
-http_access deny manager
-
-auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
-auth_param basic realm proxy
-acl authenticated proxy_auth REQUIRED
-http_access allow authenticated
-http_access deny all
-
-http_port 3128
-
-coredump_dir /var/spool/squid
-
-refresh_pattern ^ftp: 1440 20% 10080
-refresh_pattern ^gopher: 1440 0% 1440
-refresh_pattern -i (/cgi-bin/|\\?) 0 0% 0
-refresh_pattern . 0 20% 4320
-
-# Privacy / hardening
-httpd_suppress_version_string on
-visible_hostname $(hostname)
-forwarded_for delete
-request_header_access X-Forwarded-For deny all
-EOF
-msg_ok "Configured Squid"
-
-msg_info "Installing Dependencies"
-$STD apt install -y \
- squid \
- apache2-utils
-msg_ok "Installed Dependencies"
-
-msg_info "Configuring Squid Authentication"
-touch /etc/squid/passwords
-chown proxy:proxy /etc/squid/passwords
-chmod 640 /etc/squid/passwords
-$STD squid -k parse
-msg_ok "Configured Squid Authentication"
-
-msg_info "Starting Service"
-systemctl enable -q --now squid
-msg_ok "Started Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/storyteller-install.sh b/install/storyteller-install.sh
index 1df32ec27..b3b343da6 100644
--- a/install/storyteller-install.sh
+++ b/install/storyteller-install.sh
@@ -28,7 +28,7 @@ NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
fetch_and_deploy_gh_release "readium" "readium/cli" "prebuild" "latest" "/opt/readium" "readium_linux_$(arch_resolve "x86_64" "arm64").tar.gz"
ln -sf /opt/readium/readium /usr/local/bin/readium
-fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" "" "web-v2"
+fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller"
msg_info "Setting up Storyteller"
cd /opt/storyteller
diff --git a/install/sync-in-install.sh b/install/sync-in-install.sh
deleted file mode 100644
index 0550fecca..000000000
--- a/install/sync-in-install.sh
+++ /dev/null
@@ -1,82 +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/Sync-in/server
-
-source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
-color
-verb_ip6
-catch_errors
-setting_up_container
-network_check
-update_os
-
-NODE_VERSION="22" setup_nodejs
-setup_mariadb
-MARIADB_DB_NAME="sync_in" MARIADB_DB_USER="sync_in" setup_mariadb_db
-
-msg_info "Installing Sync-in"
-mkdir -p /opt/sync-in/data
-$STD npm install --prefix /opt/sync-in @sync-in/server
-msg_ok "Installed Sync-in"
-
-msg_info "Configuring Sync-in"
-ENCRYPT_KEY=$(openssl rand -hex 32)
-ACCESS_SECRET=$(openssl rand -hex 32)
-REFRESH_SECRET=$(openssl rand -hex 32)
-cat </opt/sync-in/environment.yaml
-server:
- port: 8080
-mysql:
- url: 'mysql://${MARIADB_DB_USER}:${MARIADB_DB_PASS}@localhost:3306/${MARIADB_DB_NAME}'
-auth:
- encryptionKey: '${ENCRYPT_KEY}'
- token:
- access:
- secret: '${ACCESS_SECRET}'
- refresh:
- secret: '${REFRESH_SECRET}'
-applications:
- files:
- dataPath: '/opt/sync-in/data'
-EOF
-msg_ok "Configured Sync-in"
-
-msg_info "Running Database Migrations"
-cd /opt/sync-in
-$STD npx sync-in-server migrate-db
-msg_ok "Ran Database Migrations"
-
-msg_info "Creating Admin User"
-cd /opt/sync-in
-$STD npx sync-in-server create-user
-msg_ok "Created Admin User"
-
-VERSION=$(node -pe "require('/opt/sync-in/node_modules/@sync-in/server/package.json').version" 2>/dev/null || echo "")
-[[ -n "$VERSION" ]] && echo "$VERSION" >~/.sync-in
-
-msg_info "Creating Service"
-cat </etc/systemd/system/sync-in.service
-[Unit]
-Description=Sync-in Server
-After=network.target mariadb.service
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/sync-in
-ExecStart=/opt/sync-in/node_modules/.bin/sync-in-server start
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now sync-in
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/install/trek-install.sh b/install/trek-install.sh
index 1161ce73a..c189afc1b 100644
--- a/install/trek-install.sh
+++ b/install/trek-install.sh
@@ -3,7 +3,7 @@
# 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/liketrek/TREK
+# Source: https://github.com/mauriceboe/TREK
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
@@ -20,7 +20,7 @@ $STD apt install -y \
msg_ok "Installed Dependencies"
NODE_VERSION="24" setup_nodejs
-fetch_and_deploy_gh_release "trek" "liketrek/TREK" "tarball"
+fetch_and_deploy_gh_release "trek" "mauriceboe/TREK" "tarball"
msg_info "Setup TREK"
cd /opt/trek
@@ -78,7 +78,7 @@ msg_info "Creating Service"
cat </etc/systemd/system/trek.service
[Unit]
Description=TREK Travel Planner
-Documentation=https://github.com/liketrek/TREK
+Documentation=https://github.com/mauriceboe/TREK
After=network-online.target
Wants=network-online.target
diff --git a/install/wanderer-install.sh b/install/wanderer-install.sh
index 6a8571bbf..3cebc9fef 100644
--- a/install/wanderer-install.sh
+++ b/install/wanderer-install.sh
@@ -20,8 +20,7 @@ if [[ "$(arch_resolve)" == "arm64" ]]; then
else
fetch_and_deploy_gh_release "meilisearch" "meilisearch/meilisearch" "binary" "latest" "/opt/wanderer/source/search"
fi
-mkdir -p /opt/wanderer/{source,data/pb_data,data/meili_data,data/plugins}
-[[ -e /data/plugins ]] || ln -sfn /opt/wanderer/data/plugins /data/plugins
+mkdir -p /opt/wanderer/{source,data/pb_data,data/meili_data}
fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source"
msg_info "Installing wanderer (patience)"
@@ -33,12 +32,6 @@ $STD npm ci
$STD npm run build
msg_ok "Installed wanderer"
-msg_info "Installing wanderer plugins"
-for plugin in hammerhead komoot strava; do
- fetch_and_deploy_gh_release "wanderer-plugin-${plugin}" "open-wanderer/wanderer" "prebuild" "latest" "/opt/wanderer/data/plugins" "wanderer-plugin-${plugin}.tar.gz" || msg_warn "Failed to install wanderer plugin: ${plugin}"
-done
-msg_ok "Installed wanderer plugins"
-
msg_info "Creating Service"
MEILI_KEY=$(openssl rand -hex 32)
POCKETBASE_KEY=$(openssl rand -hex 16)
diff --git a/install/webtrees-install.sh b/install/webtrees-install.sh
index 69b735e46..c2be2e79e 100644
--- a/install/webtrees-install.sh
+++ b/install/webtrees-install.sh
@@ -47,8 +47,6 @@ msg_ok "Configured Caddy"
msg_info "Automating Webtrees Setup"
cd /opt/webtrees
-mkdir -p /opt/webtrees/data
-chown -R www-data:www-data /opt/webtrees/data
WT_ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c15)
$STD sudo -u www-data php /opt/webtrees/index.php config-ini \
--dbhost=127.0.0.1 \
@@ -58,15 +56,6 @@ $STD sudo -u www-data php /opt/webtrees/index.php config-ini \
--dbname=webtrees \
--tblpfx=wt_ \
--base-url="http://${LOCAL_IP}"
-msg_info "Initializing Webtrees database schema"
-for i in {1..15}; do
- if curl -sf "http://127.0.0.1/" >/dev/null 2>&1; then
- break
- fi
- sleep 2
-done
-$STD mariadb -u webtrees -p"${MARIADB_DB_PASS}" -h 127.0.0.1 webtrees -e "SHOW TABLES LIKE 'wt_user';" | grep -q wt_user
-msg_ok "Initialized Webtrees database schema"
$STD sudo -u www-data php /opt/webtrees/index.php user Admin \
--create \
--real-name="Administrator" \
diff --git a/install/yuvomi-install.sh b/install/yuvomi-install.sh
deleted file mode 100644
index 521049586..000000000
--- a/install/yuvomi-install.sh
+++ /dev/null
@@ -1,72 +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/ulsklyc/yuvomi
-
-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 \
- python3 \
- make \
- g++ \
- libsqlcipher-dev
-msg_ok "Installed Dependencies"
-
-NODE_VERSION="22" setup_nodejs
-
-fetch_and_deploy_gh_release "yuvomi" "ulsklyc/yuvomi" "tarball"
-
-msg_info "Installing Node.js Dependencies"
-cd /opt/yuvomi
-$STD npm ci --omit=dev
-msg_ok "Installed Node.js Dependencies"
-
-msg_info "Configuring Yuvomi"
-mkdir -p /opt/yuvomi/data /opt/yuvomi/backups
-SESSION_SECRET=$(openssl rand -hex 32)
-DB_ENCRYPT_KEY=$(openssl rand -hex 32)
-cat </opt/yuvomi/.env
-PORT=3000
-NODE_ENV=production
-DB_PATH=/opt/yuvomi/data/yuvomi.db
-DB_ENCRYPTION_KEY=${DB_ENCRYPT_KEY}
-SESSION_SECRET=${SESSION_SECRET}
-RATE_LIMIT_WINDOW_MS=60000
-RATE_LIMIT_MAX_ATTEMPTS=5
-RATE_LIMIT_BLOCK_DURATION_MS=900000
-EOF
-msg_ok "Configured Yuvomi"
-
-msg_info "Creating Service"
-cat </etc/systemd/system/yuvomi.service
-[Unit]
-Description=Yuvomi Family Planner
-After=network.target
-
-[Service]
-Type=simple
-User=root
-WorkingDirectory=/opt/yuvomi
-EnvironmentFile=/opt/yuvomi/.env
-ExecStart=/usr/bin/node server/index.js
-Restart=on-failure
-RestartSec=5
-
-[Install]
-WantedBy=multi-user.target
-EOF
-systemctl enable -q --now yuvomi
-msg_ok "Created Service"
-
-motd_ssh
-customize
-cleanup_lxc
diff --git a/misc/build.func b/misc/build.func
index 53509780f..bf74bd3b6 100644
--- a/misc/build.func
+++ b/misc/build.func
@@ -3753,32 +3753,30 @@ run_addon_updates() {
}
runtime_script_status_guard() {
- local mode="${1:-}"
local script_slug="${SCRIPT_SLUG:-${NSAPP:-}}"
script_slug="$(echo "$script_slug" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')"
[[ -z "$script_slug" ]] && return 0
- local api_url="https://db.community-scripts.org/api/collections/script_scripts/records?filter=(slug='${script_slug}')&perPage=1&fields=slug,is_disabled,is_deleted,disable_message,deleted_message,pinned_version,pin_reason"
+ local api_url="https://db.community-scripts.org/api/collections/script_scripts/records?filter=(slug='${script_slug}')&perPage=1&fields=slug,is_disabled,is_deleted,disable_message,deleted_message"
local response
if ! response=$(curl -fsSL --connect-timeout 2 --max-time 3 "$api_url" 2>/dev/null); then
msg_warn "Script status check is unavailable. Continuing without status verification."
return 0
fi
- local is_deleted is_disabled deleted_message disable_message pinned_version pin_reason info_url
- if printf '%s' "$response" | grep -qE '"items":[[:space:]]*\[[[:space:]]*\]'; then
+ if ! command -v jq >/dev/null 2>&1; then
+ msg_warn "Missing jq for script status check. Continuing without status verification."
return 0
fi
- # PocketBase returns a flat, fixed-field JSON blob; sed is enough here (no jq needed).
- is_deleted=$(printf '%s' "$response" | sed -n 's/.*"is_deleted"[[:space:]]*:[[:space:]]*\(true\|false\).*/\1/p' | head -1)
- is_disabled=$(printf '%s' "$response" | sed -n 's/.*"is_disabled"[[:space:]]*:[[:space:]]*\(true\|false\).*/\1/p' | head -1)
- deleted_message=$(printf '%s' "$response" | sed -n 's/.*"deleted_message"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
- disable_message=$(printf '%s' "$response" | sed -n 's/.*"disable_message"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
- pinned_version=$(printf '%s' "$response" | sed -n 's/.*"pinned_version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
- pin_reason=$(printf '%s' "$response" | sed -n 's/.*"pin_reason"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
- is_deleted=${is_deleted:-false}
- is_disabled=${is_disabled:-false}
+ local has_record is_deleted is_disabled deleted_message disable_message info_url
+ has_record=$(printf '%s' "$response" | jq -r '.items | length')
+ [[ "$has_record" == "0" ]] && return 0
+
+ is_deleted=$(printf '%s' "$response" | jq -r '.items[0].is_deleted // false')
+ is_disabled=$(printf '%s' "$response" | jq -r '.items[0].is_disabled // false')
+ deleted_message=$(printf '%s' "$response" | jq -r '.items[0].deleted_message // ""')
+ disable_message=$(printf '%s' "$response" | jq -r '.items[0].disable_message // ""')
info_url="https://community-scripts.org/scripts/${script_slug}"
if [[ "$is_deleted" == "true" ]]; then
@@ -3808,26 +3806,6 @@ runtime_script_status_guard() {
return 1
fi
- if [[ "$mode" == "update" && -n "$pinned_version" && -n "${NSAPP:-}" ]]; then
- local current_file="$HOME/.${NSAPP}"
- if [[ -f "$current_file" ]]; then
- local installed pinned_clean installed_clean
- installed="$(<"$current_file")"
- pinned_clean="$pinned_version"
- installed_clean="$installed"
- [[ "$pinned_clean" =~ ^v[0-9] ]] && pinned_clean="${pinned_clean:1}"
- [[ "$installed_clean" =~ ^v[0-9] ]] && installed_clean="${installed_clean:1}"
- if [[ "$installed_clean" == "$pinned_clean" ]]; then
- if [[ -n "$pin_reason" ]]; then
- msg_info "You are already on the pinned version (${pinned_version}). ${pin_reason}"
- else
- msg_info "You are already on the pinned version (${pinned_version}). No newer update is offered intentionally — please do not open an issue unless you see an actual error."
- fi
- msg_info "More info: ${info_url}"
- fi
- fi
- fi
-
return 0
}
@@ -3843,7 +3821,7 @@ runtime_script_status_guard() {
start() {
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
if command -v pveversion >/dev/null 2>&1; then
- runtime_script_status_guard install || return 0
+ runtime_script_status_guard || return 0
install_script || return 0
return 0
elif [ ! -z ${PHS_SILENT+x} ] && [[ "${PHS_SILENT}" == "1" ]]; then
@@ -3851,7 +3829,7 @@ start() {
set_std_mode
ensure_profile_loaded
get_lxc_ip
- runtime_script_status_guard update || return 0
+ runtime_script_status_guard || return 0
update_script
run_addon_updates
update_motd_ip
@@ -3862,7 +3840,7 @@ start() {
set_std_mode
ensure_profile_loaded
get_lxc_ip
- runtime_script_status_guard update || return 0
+ runtime_script_status_guard || return 0
update_script
run_addon_updates
update_motd_ip
@@ -3892,7 +3870,7 @@ start() {
esac
ensure_profile_loaded
get_lxc_ip
- runtime_script_status_guard update || return 0
+ runtime_script_status_guard || return 0
update_script
run_addon_updates
update_motd_ip
diff --git a/misc/tools.func b/misc/tools.func
index cc5e66162..e8e18f4f3 100644
--- a/misc/tools.func
+++ b/misc/tools.func
@@ -36,10 +36,6 @@
#
# ==============================================================================
-# Guard against double-sourcing (core.func uses the same pattern)
-[[ -n "${_TOOLS_FUNC_LOADED:-}" ]] && return 0
-_TOOLS_FUNC_LOADED=1
-
# ------------------------------------------------------------------------------
# Debug helper - outputs to stderr when TOOLS_DEBUG is enabled
# Usage: debug_log "message"
@@ -95,17 +91,16 @@ curl_with_retry() {
while [[ $attempt -le $retries ]]; do
debug_log "curl attempt $attempt/$retries: $url"
- # Build curl command as array to avoid command injection via extra_opts
- local -a curl_args=(curl -fsSL --connect-timeout "$connect_timeout" --max-time "$timeout")
- [[ -n "$extra_opts" ]] && read -ra _extra <<<"$extra_opts" && curl_args+=("${_extra[@]}")
+ local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout"
+ [[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $extra_opts"
if [[ "$output" == "-" ]]; then
- if "${curl_args[@]}" "$url"; then
+ if $curl_cmd "$url"; then
success=true
break
fi
else
- if "${curl_args[@]}" -o "$output" "$url"; then
+ if $curl_cmd -o "$output" "$url"; then
success=true
break
fi
@@ -158,16 +153,15 @@ curl_api_with_retry() {
while [[ $attempt -le $retries ]]; do
debug_log "curl API attempt $attempt/$retries: $url"
- # Build curl command as array to avoid command injection via extra_opts
- local -a curl_args=(curl -fsSL --connect-timeout "$connect_timeout" --max-time "$timeout" -w '%{http_code}')
- [[ -n "$extra_opts" ]] && read -ra _extra <<<"$extra_opts" && curl_args+=("${_extra[@]}")
+ local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout -w '%{http_code}'"
+ [[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $extra_opts"
if [[ -n "$body_file" ]]; then
- http_code=$("${curl_args[@]}" -o "$body_file" "$url" 2>/dev/null) || true
+ http_code=$($curl_cmd -o "$body_file" "$url" 2>/dev/null) || true
else
# Capture body and http_code separately
local tmp_body="/tmp/curl_api_body_$$"
- http_code=$("${curl_args[@]}" -o "$tmp_body" "$url" 2>/dev/null) || true
+ http_code=$($curl_cmd -o "$tmp_body" "$url" 2>/dev/null) || true
if [[ -f "$tmp_body" ]]; then
cat "$tmp_body"
rm -f "$tmp_body"
@@ -310,10 +304,7 @@ edit_yaml_config() {
return 1
fi
- # Escape sed metacharacters in value (| and &) to prevent injection
- local escaped_value="${value//|/\\|}"
- escaped_value="${escaped_value//&/\\&}"
- sed -i "s|^\([[:space:]]*${key}[[:space:]]*:\).*|\1 ${escaped_value}|" "$file"
+ sed -i "s|^\([[:space:]]*${key}[[:space:]]*:\).*|\1 ${value}|" "$file"
}
# ------------------------------------------------------------------------------
@@ -1696,6 +1687,10 @@ is_ubuntu() {
[[ "$(get_os_info id)" == "ubuntu" ]]
}
+is_alpine() {
+ [[ "$(get_os_info id)" == "alpine" ]]
+}
+
# ------------------------------------------------------------------------------
# Get Debian/Ubuntu major version
# ------------------------------------------------------------------------------
@@ -2459,10 +2454,8 @@ start_timer() {
end_timer() {
local start_time="$1"
local label="${2:-Operation}"
- local end_time
- end_time=$(date +%s)
+ local end_time=$(date +%s)
local duration=$((end_time - start_time))
- echo "${label} took ${duration}s"
}
# ------------------------------------------------------------------------------
@@ -2483,150 +2476,6 @@ verify_gpg_fingerprint() {
return 65
}
-# ------------------------------------------------------------------------------
-# _download_source_tarball [curl args...]
-#
-# Downloads a source .tar.gz to and verifies the gzip stream is complete
-# before returning. Source forges (GitHub/GitLab/Codeberg) build these archives
-# on the fly; for large repos the response is occasionally a truncated-but-
-# cleanly-closed gzip that curl accepts as success (HTTP 200) and which then
-# fails at extraction time. We validate with `gzip -t` and re-download on
-# failure, and abort stalled transfers (--speed-time) so a hung generation
-# retries instead of blocking for minutes. Extra args pass through to curl
-# (e.g. auth headers like -H "PRIVATE-TOKEN: ...").
-#
-# Returns: 0 on success, 250 on persistent failure.
-# ------------------------------------------------------------------------------
-_download_source_tarball() {
- local url="$1" dest="$2"
- shift 2
- local attempt max=3
- for ((attempt = 1; attempt <= max; attempt++)); do
- if curl --connect-timeout 15 --max-time 900 --speed-limit 1024 --speed-time 60 \
- -fsSL "$@" -o "$dest" "$url" && gzip -t "$dest" 2>/dev/null; then
- return 0
- fi
- rm -f "$dest"
- ((attempt < max)) && {
- msg_warn "Source archive download failed or incomplete (attempt ${attempt}/${max}), retrying..."
- sleep $((attempt * 3))
- }
- done
- return 250
-}
-
-# ------------------------------------------------------------------------------
-# _deploy_source_tarball
-#
-# Shared tail for the *source tarball* modes of the fetch_and_deploy_* helpers
-# (GitHub/GitLab/Codeberg archive tarballs that contain a single top-level
-# directory). Extracts into , then copies the contents
-# of that top-level directory into .
-#
-# - Honors CLEAN_INSTALL=1 (wipes first, dotfiles included).
-# - Does NOT own : the caller creates it and is responsible for its
-# cleanup (typically via a RETURN trap on its tmpdir).
-# - cp failures are non-fatal here, matching the previous inline behavior.
-#
-# Returns: 0 on success (or non-fatal cp failure), 251 on extraction failure.
-# ------------------------------------------------------------------------------
-_deploy_source_tarball() {
- local tarball="$1" target="$2" workdir="$3"
-
- mkdir -p "$target"
- if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
- find "${target:?}" -mindepth 1 -delete
- fi
-
- tar --no-same-owner -xzf "$tarball" -C "$workdir" || {
- msg_error "Failed to extract tarball"
- return 251
- }
-
- local unpack_dir
- unpack_dir=$(find "$workdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
-
- shopt -s dotglob nullglob
- cp -r "$unpack_dir"/* "$target/"
- shopt -u dotglob nullglob
- return 0
-}
-
-# ------------------------------------------------------------------------------
-# _deploy_unpacked_archive
-#
-# Shared tail for the *prebuild* modes of the fetch_and_deploy_*_release helpers
-# (release assets shipped as .zip / .tar.* / .tgz / .txz). Extracts the archive
-# into , then copies its payload into . If the archive contains
-# a single top-level directory, that directory is stripped (its contents land
-# directly in ); otherwise the archive contents are copied as-is.
-#
-# - Honors CLEAN_INSTALL=1 (wipes first, dotfiles included).
-# - Does NOT own : the caller creates it and cleans it up.
-#
-# Returns: 0 on success, 65 on unsupported format, 251 on extraction failure,
-# 252 on copy failure / empty archive.
-# ------------------------------------------------------------------------------
-_deploy_unpacked_archive() {
- local archive="$1" target="$2" workdir="$3"
- local filename="${archive##*/}"
-
- mkdir -p "$target"
- if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
- find "${target:?}" -mindepth 1 -delete
- fi
-
- if [[ "$filename" == *.zip ]]; then
- ensure_dependencies unzip
- unzip -q "$archive" -d "$workdir" || {
- msg_error "Failed to extract ZIP archive"
- return 251
- }
- elif [[ "$filename" == *.tar.* || "$filename" == *.tgz || "$filename" == *.txz ]]; then
- tar --no-same-owner -xf "$archive" -C "$workdir" || {
- msg_error "Failed to extract TAR archive"
- return 251
- }
- else
- msg_error "Unsupported archive format: $filename"
- return 65
- fi
-
- local top_entries inner_dir
- top_entries=$(find "$workdir" -mindepth 1 -maxdepth 1)
- if [[ "$(echo "$top_entries" | wc -l)" -eq 1 && -d "$top_entries" ]]; then
- inner_dir="$top_entries"
- shopt -s dotglob nullglob
- if compgen -G "$inner_dir/*" >/dev/null; then
- cp -r "$inner_dir"/* "$target/" || {
- msg_error "Failed to copy contents from $inner_dir to $target"
- shopt -u dotglob nullglob
- return 252
- }
- else
- msg_error "Inner directory is empty: $inner_dir"
- shopt -u dotglob nullglob
- return 252
- fi
- shopt -u dotglob nullglob
- else
- shopt -s dotglob nullglob
- if compgen -G "$workdir/*" >/dev/null; then
- cp -r "$workdir"/* "$target/" || {
- msg_error "Failed to copy contents to $target"
- shopt -u dotglob nullglob
- return 252
- }
- else
- msg_error "Unpacked archive is empty"
- shopt -u dotglob nullglob
- return 252
- fi
- shopt -u dotglob nullglob
- fi
- return 0
-}
-
# ------------------------------------------------------------------------------
# Fetches and deploys a GitHub tag-based source tarball.
#
@@ -2675,200 +2524,41 @@ fetch_and_deploy_gh_tag() {
local tmpdir
tmpdir=$(mktemp -d) || return 1
- trap 'rm -rf "$tmpdir"' RETURN
local tarball_url="https://github.com/${repo}/archive/refs/tags/${version}.tar.gz"
local filename="${app_lc}-${version}.tar.gz"
msg_info "Fetching GitHub tag: ${app} (${version})"
- _download_source_tarball "$tarball_url" "$tmpdir/$filename" || {
+ download_file "$tarball_url" "$tmpdir/$filename" || {
msg_error "Download failed: $tarball_url"
+ rm -rf "$tmpdir"
return 7
}
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 251
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+ tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
+ msg_error "Failed to extract tarball"
+ rm -rf "$tmpdir"
+ return 251
+ }
+
+ local unpack_dir
+ unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
+
+ shopt -s dotglob nullglob
+ cp -r "$unpack_dir"/* "$target/"
+ shopt -u dotglob nullglob
+
+ rm -rf "$tmpdir"
echo "$version" >"$version_file"
msg_ok "Deployed ${app} ${version} to ${target}"
return 0
}
-# ------------------------------------------------------------------------------
-# Get the latest GitLab repository tag matching a glob pattern.
-#
-# Description:
-# - Queries the GitLab repository tags API (up to 100 tags per page)
-# - Filters tag names against a shell glob pattern (e.g. "web-v*" or "mobile-v*")
-# - Always excludes pre-release tags (those containing alpha, beta, or rc)
-# - Sorts matching tags with `sort -V` and returns the highest one
-# - Supports GITLAB_TOKEN for private/rate-limited projects
-#
-# Usage:
-# get_latest_gl_tag "owner/repo" "web-v*"
-# get_latest_gl_tag "owner/repo" "mobile-v*"
-# get_latest_gl_tag "owner/repo" # returns newest tag (no filter)
-#
-# Arguments:
-# $1 - GitLab repo path (namespace/project, e.g. "mygroup/myapp")
-# $2 - Optional glob pattern to filter tag names (e.g. "web-v*")
-#
-# Returns:
-# Latest matching tag name on stdout, or non-zero on failure
-# ------------------------------------------------------------------------------
-get_latest_gl_tag() {
- local repo="$1"
- local pattern="${2:-}"
-
- local repo_encoded
- repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
-
- local api_base="https://gitlab.com/api/v4/projects/${repo_encoded}/repository/tags"
- local api_timeout="--connect-timeout 10 --max-time 60"
-
- local header=()
- [[ -n "${GITLAB_TOKEN:-}" ]] && header=(-H "PRIVATE-TOKEN: $GITLAB_TOKEN")
-
- # If a pattern is given, pass it as a regex search to reduce server-side results.
- # GitLab ?search= supports anchored regex; convert leading glob prefix to regex anchor.
- local search_param=""
- if [[ -n "$pattern" ]]; then
- # Strip trailing wildcard for the search hint (server-side prefix filter).
- local prefix="${pattern%%\**}"
- [[ -n "$prefix" ]] && search_param="?search=^${prefix}&per_page=100" || search_param="?per_page=100"
- else
- search_param="?per_page=100"
- fi
-
- local temp_file
- temp_file=$(mktemp) || return 1
-
- local http_code
- http_code=$(curl $api_timeout -sSL -w "%{http_code}" -o "$temp_file" \
- "${header[@]}" "${api_base}${search_param}" 2>/dev/null) || true
-
- if [[ "$http_code" != "200" ]]; then
- rm -f "$temp_file"
- msg_error "GitLab tags API returned HTTP $http_code for $repo"
- return 22
- fi
-
- local tag=""
- if [[ -n "$pattern" ]]; then
- # Client-side glob filter + pre-release exclusion, then version-sort to pick the highest match.
- tag=$(jq -r '.[].name' "$temp_file" 2>/dev/null | while IFS= read -r t; do
- case "$t" in
- *alpha* | *beta* | *rc*) continue ;;
- $pattern) echo "$t" ;;
- esac
- done | sort -V | tail -n1)
- else
- # No pattern: skip pre-release tags, take the first remaining (newest) one.
- tag=$(jq -r '.[].name' "$temp_file" 2>/dev/null |
- grep -Eiv '(alpha|beta|rc)' |
- head -n1)
- fi
-
- rm -f "$temp_file"
-
- if [[ -z "$tag" ]]; then
- msg_error "No tags matching '${pattern:-*}' found for ${repo}"
- return 250
- fi
-
- echo "$tag"
-}
-
-# ------------------------------------------------------------------------------
-# Fetches and deploys a GitLab tag-based source tarball.
-#
-# Description:
-# - Resolves the latest tag matching the given glob pattern via get_latest_gl_tag
-# (or uses the exact tag if one is provided instead of "latest")
-# - Downloads the GitLab source tarball for that tag
-# - Extracts it to the target directory
-# - Writes the resolved tag to ~/. for update-checking
-#
-# Usage:
-# fetch_and_deploy_gl_tag "myapp" "mygroup/myrepo" "web-v*"
-# fetch_and_deploy_gl_tag "myapp" "mygroup/myrepo" "mobile-v*" "/opt/myapp"
-# fetch_and_deploy_gl_tag "myapp" "mygroup/myrepo" "v*" # any v-tag
-# fetch_and_deploy_gl_tag "myapp" "mygroup/myrepo" "web-v3.0*" # narrow version range
-#
-# Arguments:
-# $1 - App name (used for version file ~/. and lowercase tarball name)
-# $2 - GitLab repo path (namespace/project, e.g. "mygroup/myapp")
-# $3 - Tag pattern: glob (e.g. "web-v*") or exact tag (e.g. "web-v3.0.0").
-# Use "latest" to fetch the single newest tag with no pattern filter.
-# $4 - Target directory (default: /opt/$app)
-#
-# Notes:
-# - Supports CLEAN_INSTALL=1 to wipe target before extracting
-# - Supports GITLAB_TOKEN for private/rate-limited projects
-# - For repos that only publish tags, not formal GitLab Releases
-# (use fetch_and_deploy_gl_release for proper Releases with assets)
-# ------------------------------------------------------------------------------
-fetch_and_deploy_gl_tag() {
- local app="$1"
- local repo="$2"
- local tag_pattern="${3:-latest}"
- local target="${4:-/opt/$app}"
-
- local app_lc=""
- app_lc="$(echo "${app,,}" | tr -d ' ')"
- local version_file="$HOME/.${app_lc}"
-
- local api_timeout="--connect-timeout 10 --max-time 60"
- local download_timeout="--connect-timeout 15 --max-time 900"
-
- local header=()
- [[ -n "${GITLAB_TOKEN:-}" ]] && header=(-H "PRIVATE-TOKEN: $GITLAB_TOKEN")
-
- # Resolve the tag: if caller passed a glob/latest, query the API.
- # If caller passed an exact tag (no wildcards), use it directly.
- local resolved_tag="$tag_pattern"
- if [[ "$tag_pattern" == "latest" || "$tag_pattern" == *"*"* || "$tag_pattern" == *"?"* ]]; then
- local glob_arg=""
- [[ "$tag_pattern" != "latest" ]] && glob_arg="$tag_pattern"
- resolved_tag=$(get_latest_gl_tag "$repo" "$glob_arg") || {
- msg_error "Failed to determine latest tag matching '${tag_pattern}' for ${repo}"
- return 250
- }
- fi
-
- local current_version=""
- [[ -f "$version_file" ]] && current_version=$(<"$version_file")
-
- if [[ "$current_version" == "$resolved_tag" ]]; then
- msg_ok "$app is already up-to-date ($resolved_tag)"
- return 0
- fi
-
- local repo_encoded
- repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
-
- # GitLab source tarball URL (no release needed, works for any tag).
- local version_safe="${resolved_tag//\//-}"
- local tarball_url="https://gitlab.com/${repo}/-/archive/${resolved_tag}/${app_lc}-${version_safe}.tar.gz"
-
- local tmpdir
- tmpdir=$(mktemp -d) || return 1
- trap 'rm -rf "$tmpdir"' RETURN
- local filename="${app_lc}-${version_safe}.tar.gz"
-
- msg_info "Fetching GitLab tag: ${app} (${resolved_tag})"
-
- _download_source_tarball "$tarball_url" "$tmpdir/$filename" "${header[@]}" || {
- msg_error "Download failed: $tarball_url"
- return 7
- }
-
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 251
-
- echo "$resolved_tag" >"$version_file"
- msg_ok "Deployed ${app} ${resolved_tag} to ${target}"
- return 0
-}
-
# ------------------------------------------------------------------------------
# Checks for new GitHub tag (for repos without releases).
#
@@ -2943,7 +2633,6 @@ check_for_gh_release() {
local source="$2"
local pinned_version_in="${3:-}" # optional
local pin_reason="${4:-}" # optional reason shown to user
- local tag_prefix="${5:-}" # optional tag prefix filter (e.g. web-v2)
local app_lc=""
app_lc="$(echo "${app,,}" | tr -d ' ')"
local current_file="$HOME/.${app_lc}"
@@ -2999,7 +2688,7 @@ check_for_gh_release() {
rm -f "$gh_check_json"
fi
- if [[ -z "$pinned_version_in" && -z "$tag_prefix" ]]; then
+ if [[ -z "$pinned_version_in" ]]; then
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
@@ -3027,7 +2716,7 @@ check_for_gh_release() {
rm -f "$gh_check_json"
fi
- # If no releases yet (pinned version, tag prefix, OR /latest failed), fetch up to 100
+ # If no releases yet (pinned version OR /latest failed), fetch up to 100
if [[ -z "$releases_json" ]]; then
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \
-H 'Accept: application/vnd.github+json' \
@@ -3065,18 +2754,9 @@ check_for_gh_release() {
rm -f "$gh_check_json"
fi
- if [[ -n "$tag_prefix" ]]; then
- mapfile -t raw_tags < <(jq -r --arg p "$tag_prefix" \
- '.[] | select(.draft==false and .prerelease==false) | select(.tag_name | startswith($p)) | .tag_name' <<<"$releases_json")
- else
- mapfile -t raw_tags < <(jq -r '.[] | select(.draft==false and .prerelease==false) | .tag_name' <<<"$releases_json")
- fi
+ mapfile -t raw_tags < <(jq -r '.[] | select(.draft==false and .prerelease==false) | .tag_name' <<<"$releases_json")
if ((${#raw_tags[@]} == 0)); then
- if [[ -n "$tag_prefix" ]]; then
- msg_error "No stable releases matching prefix '${tag_prefix}' found for ${app}"
- else
- msg_error "No stable releases found for ${app}"
- fi
+ msg_error "No stable releases found for ${app}"
return 250
fi
@@ -3560,7 +3240,6 @@ fetch_and_deploy_codeberg_release() {
local tmpdir
tmpdir=$(mktemp -d) || return 252
- trap 'rm -rf "$tmpdir"' RETURN
msg_info "Fetching Codeberg tag: $app ($tag_name)"
@@ -3571,19 +3250,37 @@ fetch_and_deploy_codeberg_release() {
# Codeberg archive URL format: https://codeberg.org/{owner}/{repo}/archive/{tag}.tar.gz
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
- if _download_source_tarball "$archive_url" "$tmpdir/$filename"; then
+ if curl_download "$tmpdir/$filename" "$archive_url"; then
download_success=true
fi
if [[ "$download_success" != "true" ]]; then
msg_error "Download failed for $app ($tag_name)"
+ rm -rf "$tmpdir"
return 250
fi
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 251
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
+ msg_error "Failed to extract tarball"
+ rm -rf "$tmpdir"
+ return 251
+ }
+
+ local unpack_dir
+ unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
+
+ shopt -s dotglob nullglob
+ cp -r "$unpack_dir"/* "$target/"
+ shopt -u dotglob nullglob
echo "$version" >"$version_file"
msg_ok "Deployed: $app ($version)"
+ rm -rf "$tmpdir"
return 0
fi
@@ -3602,7 +3299,7 @@ fetch_and_deploy_codeberg_release() {
local codeberg_rel_json
codeberg_rel_json=$(mktemp /tmp/tools-codeberg-rel-XXXXXX) || return 73
- trap 'rm -f "$codeberg_rel_json"; rm -rf "${tmpdir:-}" "${unpack_tmp:-}"' RETURN
+ trap 'rm -f "$codeberg_rel_json"' RETURN
local attempt=0 success=false resp http_code
@@ -3656,16 +3353,32 @@ fetch_and_deploy_codeberg_release() {
# Codeberg archive URL format
local archive_url="https://codeberg.org/$repo/archive/${tag_name}.tar.gz"
- if _download_source_tarball "$archive_url" "$tmpdir/$filename"; then
+ if curl_download "$tmpdir/$filename" "$archive_url"; then
download_success=true
fi
if [[ "$download_success" != "true" ]]; then
msg_error "Download failed for $app ($tag_name)"
+ rm -rf "$tmpdir"
return 250
fi
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 251
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
+ msg_error "Failed to extract tarball"
+ rm -rf "$tmpdir"
+ return 251
+ }
+ local unpack_dir
+ unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
+
+ shopt -s dotglob nullglob
+ cp -r "$unpack_dir"/* "$target/"
+ shopt -u dotglob nullglob
### Binary Mode ###
elif [[ "$mode" == "binary" ]]; then
@@ -3713,12 +3426,14 @@ fetch_and_deploy_codeberg_release() {
if [[ -z "$url_match" ]]; then
msg_error "No suitable .deb asset found for $app"
+ rm -rf "$tmpdir"
return 252
fi
filename="${url_match##*/}"
curl_download "$tmpdir/$filename" "$url_match" || {
msg_error "Download failed: $url_match"
+ rm -rf "$tmpdir"
return 250
}
@@ -3726,6 +3441,7 @@ fetch_and_deploy_codeberg_release() {
$STD apt install -y "$tmpdir/$filename" || {
$STD dpkg -i "$tmpdir/$filename" || {
_diagnose_deb_failure "$tmpdir/$filename"
+ rm -rf "$tmpdir"
return 100
}
}
@@ -3736,6 +3452,7 @@ fetch_and_deploy_codeberg_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'prebuild' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 65
}
@@ -3752,18 +3469,77 @@ fetch_and_deploy_codeberg_release() {
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 252
}
filename="${asset_url##*/}"
curl_download "$tmpdir/$filename" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 250
}
local unpack_tmp
unpack_tmp=$(mktemp -d)
- _deploy_unpacked_archive "$tmpdir/$filename" "$target" "$unpack_tmp" || return
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ if [[ "$filename" == *.zip ]]; then
+ ensure_dependencies unzip
+ unzip -q "$tmpdir/$filename" -d "$unpack_tmp" || {
+ msg_error "Failed to extract ZIP archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 251
+ }
+ elif [[ "$filename" == *.tar.* || "$filename" == *.tgz ]]; then
+ tar --no-same-owner -xf "$tmpdir/$filename" -C "$unpack_tmp" || {
+ msg_error "Failed to extract TAR archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 251
+ }
+ else
+ msg_error "Unsupported archive format: $filename"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 251
+ fi
+
+ local top_dirs
+ top_dirs=$(find "$unpack_tmp" -mindepth 1 -maxdepth 1 -type d | wc -l)
+ local top_entries inner_dir
+ top_entries=$(find "$unpack_tmp" -mindepth 1 -maxdepth 1)
+ if [[ "$(echo "$top_entries" | wc -l)" -eq 1 && -d "$top_entries" ]]; then
+ inner_dir="$top_entries"
+ shopt -s dotglob nullglob
+ if compgen -G "$inner_dir/*" >/dev/null; then
+ cp -r "$inner_dir"/* "$target/" || {
+ msg_error "Failed to copy contents from $inner_dir to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ }
+ else
+ msg_error "Inner directory is empty: $inner_dir"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ fi
+ shopt -u dotglob nullglob
+ else
+ shopt -s dotglob nullglob
+ if compgen -G "$unpack_tmp/*" >/dev/null; then
+ cp -r "$unpack_tmp"/* "$target/" || {
+ msg_error "Failed to copy contents to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ }
+ else
+ msg_error "Unpacked archive is empty"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ fi
+ shopt -u dotglob nullglob
+ fi
### Singlefile Mode ###
elif [[ "$mode" == "singlefile" ]]; then
@@ -3771,6 +3547,7 @@ fetch_and_deploy_codeberg_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'singlefile' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 65
}
@@ -3787,6 +3564,7 @@ fetch_and_deploy_codeberg_release() {
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 252
}
@@ -3799,6 +3577,7 @@ fetch_and_deploy_codeberg_release() {
curl_download "$target/$target_file" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 250
}
@@ -3808,11 +3587,13 @@ fetch_and_deploy_codeberg_release() {
else
msg_error "Unknown mode: $mode"
+ rm -rf "$tmpdir"
return 65
fi
echo "$version" >"$version_file"
msg_ok "Deployed: $app ($version)"
+ rm -rf "$tmpdir"
}
# ------------------------------------------------------------------------------
@@ -3979,7 +3760,6 @@ fetch_and_deploy_gh_release() {
local version="${var_appversion:-${4:-latest}}"
local target="${5:-/opt/$app}"
local asset_pattern="${6:-}"
- local tag_prefix="${7:-}"
# Validate app name to prevent /root/. directory issues
if [[ -z "$app" ]]; then
@@ -4009,13 +3789,7 @@ fetch_and_deploy_gh_release() {
TOOLS_GH_REL_JSON="$gh_rel_json"
local api_url="https://api.github.com/repos/$repo/releases"
- if [[ "$version" != "latest" ]]; then
- api_url="$api_url/tags/$version"
- elif [[ -n "$tag_prefix" ]]; then
- api_url="$api_url?per_page=100"
- else
- api_url="$api_url/latest"
- fi
+ [[ "$version" != "latest" ]] && api_url="$api_url/tags/$version" || api_url="$api_url/latest"
local header=()
[[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN")
@@ -4078,14 +3852,6 @@ fetch_and_deploy_gh_release() {
local json tag_name
json=$(<"$gh_rel_json")
- if [[ "$version" == "latest" && -n "$tag_prefix" ]]; then
- json=$(echo "$json" | jq --arg p "$tag_prefix" \
- '[.[] | select(.draft==false and .prerelease==false) | select(.tag_name | startswith($p))][0] // empty')
- if [[ -z "$json" || "$json" == "null" ]]; then
- msg_error "No stable release matching prefix '${tag_prefix}' found for $repo on GitHub"
- return 1
- fi
- fi
tag_name=$(echo "$json" | jq -r '.tag_name // .name // empty')
# Only strip leading 'v' when followed by a digit (e.g. v1.2.3), not words like "version/..."
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
@@ -4099,7 +3865,6 @@ fetch_and_deploy_gh_release() {
local tmpdir
tmpdir=$(mktemp -d) || return 1
- trap 'rm -rf "$tmpdir" "${unpack_tmp:-}"' RETURN
local filename="" url=""
msg_info "Fetching GitHub release: $app ($version)"
@@ -4114,12 +3879,28 @@ fetch_and_deploy_gh_release() {
local direct_tarball_url="https://github.com/$repo/archive/refs/tags/$tag_name.tar.gz"
filename="${app_lc}-${version_safe}.tar.gz"
- _download_source_tarball "$direct_tarball_url" "$tmpdir/$filename" || {
+ curl_download "$tmpdir/$filename" "$direct_tarball_url" || {
msg_error "Download failed: $direct_tarball_url"
+ rm -rf "$tmpdir"
return 250
}
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 251
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
+ msg_error "Failed to extract tarball"
+ rm -rf "$tmpdir"
+ return 251
+ }
+ local unpack_dir
+ unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
+
+ shopt -s dotglob nullglob
+ cp -r "$unpack_dir"/* "$target/"
+ shopt -u dotglob nullglob
### Binary Mode ###
elif [[ "$mode" == "binary" ]]; then
@@ -4204,12 +3985,14 @@ fetch_and_deploy_gh_release() {
if [[ -z "$url_match" ]]; then
msg_error "No suitable .deb asset found for $app"
+ rm -rf "$tmpdir"
return 252
fi
filename="${url_match##*/}"
curl_download "$tmpdir/$filename" "$url_match" || {
msg_error "Download failed: $url_match"
+ rm -rf "$tmpdir"
return 250
}
@@ -4222,6 +4005,7 @@ fetch_and_deploy_gh_release() {
DEBIAN_FRONTEND=noninteractive SYSTEMD_OFFLINE=1 $STD apt install -y $dpkg_opts "$tmpdir/$filename" || {
SYSTEMD_OFFLINE=1 $STD dpkg -i "$tmpdir/$filename" || {
_diagnose_deb_failure "$tmpdir/$filename"
+ rm -rf "$tmpdir"
return 100
}
}
@@ -4232,6 +4016,7 @@ fetch_and_deploy_gh_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'prebuild' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 65
}
@@ -4267,18 +4052,79 @@ fetch_and_deploy_gh_release() {
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 252
}
filename="${asset_url##*/}"
curl_download "$tmpdir/$filename" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 250
}
local unpack_tmp
unpack_tmp=$(mktemp -d)
- _deploy_unpacked_archive "$tmpdir/$filename" "$target" "$unpack_tmp" || return
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ if [[ "$filename" == *.zip ]]; then
+ ensure_dependencies unzip
+ unzip -q "$tmpdir/$filename" -d "$unpack_tmp" || {
+ msg_error "Failed to extract ZIP archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 251
+ }
+ elif [[ "$filename" == *.tar.* || "$filename" == *.tgz || "$filename" == *.txz ]]; then
+ tar --no-same-owner -xf "$tmpdir/$filename" -C "$unpack_tmp" || {
+ msg_error "Failed to extract TAR archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 251
+ }
+ else
+ msg_error "Unsupported archive format: $filename"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 65
+ fi
+
+ local top_dirs
+ top_dirs=$(find "$unpack_tmp" -mindepth 1 -maxdepth 1 -type d | wc -l)
+ local top_entries inner_dir
+ top_entries=$(find "$unpack_tmp" -mindepth 1 -maxdepth 1)
+ if [[ "$(echo "$top_entries" | wc -l)" -eq 1 && -d "$top_entries" ]]; then
+ # Strip leading folder
+ inner_dir="$top_entries"
+ shopt -s dotglob nullglob
+ if compgen -G "$inner_dir/*" >/dev/null; then
+ cp -r "$inner_dir"/* "$target/" || {
+ msg_error "Failed to copy contents from $inner_dir to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ }
+ else
+ msg_error "Inner directory is empty: $inner_dir"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ fi
+ shopt -u dotglob nullglob
+ else
+ # Copy all contents
+ shopt -s dotglob nullglob
+ if compgen -G "$unpack_tmp/*" >/dev/null; then
+ cp -r "$unpack_tmp"/* "$target/" || {
+ msg_error "Failed to copy contents to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ }
+ else
+ msg_error "Unpacked archive is empty"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 252
+ fi
+ shopt -u dotglob nullglob
+ fi
### Singlefile Mode ###
elif [[ "$mode" == "singlefile" ]]; then
@@ -4286,6 +4132,7 @@ fetch_and_deploy_gh_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'singlefile' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 65
}
@@ -4320,6 +4167,7 @@ fetch_and_deploy_gh_release() {
fi
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 252
}
@@ -4332,6 +4180,7 @@ fetch_and_deploy_gh_release() {
curl_download "$target/$target_file" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 250
}
@@ -4341,11 +4190,13 @@ fetch_and_deploy_gh_release() {
else
msg_error "Unknown mode: $mode"
+ rm -rf "$tmpdir"
return 65
fi
echo "$version" >"$version_file"
msg_ok "Deployed: $app ($version)"
+ rm -rf "$tmpdir"
}
# ------------------------------------------------------------------------------
@@ -4587,20 +4438,20 @@ setup_composer() {
# - Cleans up legacy repository files
#
# Usage:
-# setup_docker # Uses official Docker repo (recommended)
-# USE_DOCKER_REPO=false setup_docker # Uses distro docker.io package
+# setup_docker # Uses distro package (recommended)
+# USE_DOCKER_REPO=true setup_docker # Uses official Docker repo
# DOCKER_PORTAINER="true" setup_docker
# DOCKER_LOG_DRIVER="json-file" setup_docker
#
# Variables:
-# USE_DOCKER_REPO - Set to "false" to use distro docker.io package
-# (default: true, uses official Docker repository)
+# USE_DOCKER_REPO - Set to "true" to use official Docker repository
+# (default: false, uses distro docker.io package)
# DOCKER_PORTAINER - Install Portainer CE (optional, "true" to enable)
# DOCKER_LOG_DRIVER - Log driver (optional, default: "journald")
# DOCKER_SKIP_UPDATES - Skip container update check (optional, "true" to skip)
#
# Features:
-# - Uses official Docker repository by default
+# - Uses stable distro packages by default
# - Migrates from get.docker.com to repository-based installation
# - Updates Docker Engine if newer version available
# - Interactive per-container update prompt (Y/N, 60 s auto-no)
@@ -4616,7 +4467,7 @@ _docker_is_noninteractive() {
setup_docker() {
local docker_installed=false
local portainer_installed=false
- local USE_DOCKER_REPO="${USE_DOCKER_REPO:-true}"
+ local USE_DOCKER_REPO="${USE_DOCKER_REPO:-false}"
# Check if Docker is already installed
if command -v docker &>/dev/null; then
@@ -4631,7 +4482,7 @@ setup_docker() {
msg_info "Portainer container detected"
fi
- # Scenario 1: Use distro repository (opt-out via USE_DOCKER_REPO=false)
+ # Scenario 1: Use distro repository (default, most stable)
if [[ "$USE_DOCKER_REPO" != "true" && "$USE_DOCKER_REPO" != "TRUE" && "$USE_DOCKER_REPO" != "1" ]]; then
# Install or upgrade Docker from distro repo
@@ -6895,11 +6746,9 @@ setup_mariadb_db() {
msg_info "Setting up MariaDB Database"
- # Use --defaults-extra-file to pass credentials safely and escape identifiers
- # to prevent SQL injection via DB name / user / password
- $STD mariadb -u root -e "CREATE DATABASE \`${MARIADB_DB_NAME//\`/\`\`}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
- $STD mariadb -u root -e "CREATE USER '${MARIADB_DB_USER//\'/\'\'}'@'localhost' IDENTIFIED BY '${MARIADB_DB_PASS//\'/\'\'}';"
- $STD mariadb -u root -e "GRANT ALL ON \`${MARIADB_DB_NAME//\`/\`\`}\`.* TO '${MARIADB_DB_USER//\'/\'\'}'@'localhost';"
+ $STD mariadb -u root -e "CREATE DATABASE \`$MARIADB_DB_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
+ $STD mariadb -u root -e "CREATE USER '$MARIADB_DB_USER'@'localhost' IDENTIFIED BY '$MARIADB_DB_PASS';"
+ $STD mariadb -u root -e "GRANT ALL ON \`$MARIADB_DB_NAME\`.* TO '$MARIADB_DB_USER'@'localhost';"
# Optional extra grants
if [[ -n "${MARIADB_DB_EXTRA_GRANTS:-}" ]]; then
@@ -7081,7 +6930,7 @@ setup_meilisearch() {
MEILI_DB_PATH="${MEILI_DB_PATH:-/var/lib/meilisearch/data}"
msg_info "Removing old MeiliSearch database for migration"
- find "${MEILI_DB_PATH:?}" -mindepth 1 -delete
+ rm -rf "${MEILI_DB_PATH:?}"/*
# Import dump using CLI flag (this is the supported method)
local DUMP_FILE="${MEILI_DUMP_DIR}/${DUMP_UID}.dump"
@@ -7355,18 +7204,6 @@ setup_mongodb() {
mkdir -p /var/lib/mongodb
chown -R mongodb:mongodb /var/lib/mongodb
- local KERNEL_VERSION MONGO_MAJOR
- KERNEL_VERSION=$(uname -r | cut -d- -f1)
- MONGO_MAJOR="${MONGO_VERSION%%.*}"
- if ((MONGO_MAJOR >= 8)) && [[ "$(printf '%s\n' "6.19" "$KERNEL_VERSION" | sort -V | head -n1)" == "6.19" ]]; then
- mkdir -p /etc/systemd/system/mongod.service.d
- cat </etc/systemd/system/mongod.service.d/rseq.conf
-[Service]
-Environment=GLIBC_TUNABLES=glibc.pthread.rseq=1
-EOF
- systemctl daemon-reload
- fi
-
$STD systemctl enable mongod || {
msg_warn "Failed to enable mongod service"
}
@@ -8541,14 +8378,8 @@ setup_postgresql_db() {
fi
msg_info "Setting up PostgreSQL Database"
- # Escape single quotes in identifiers to prevent SQL injection
- local _pg_user_escaped _pg_pass_escaped _pg_db_escaped
- _pg_user_escaped="${PG_DB_USER//\'/\'\'}"
- _pg_pass_escaped="${PG_DB_PASS//\'/\'\'}"
- _pg_db_escaped="${PG_DB_NAME//\'/\'\'}"
-
- $STD sudo -u postgres psql -c "CREATE ROLE $_pg_user_escaped WITH LOGIN PASSWORD '$_pg_pass_escaped';"
- $STD sudo -u postgres psql -c "CREATE DATABASE $_pg_db_escaped WITH OWNER $_pg_user_escaped ENCODING 'UTF8' TEMPLATE template0;"
+ $STD sudo -u postgres psql -c "CREATE ROLE $PG_DB_USER WITH LOGIN PASSWORD '$PG_DB_PASS';"
+ $STD sudo -u postgres psql -c "CREATE DATABASE $PG_DB_NAME WITH OWNER $PG_DB_USER ENCODING 'UTF8' TEMPLATE template0;"
# Configure pg_cron database BEFORE creating the extension (must be set before pg_cron loads)
if [[ -n "${PG_DB_EXTENSIONS:-}" ]] && [[ ",${PG_DB_EXTENSIONS//[[:space:]]/}," == *",pg_cron,"* ]]; then
@@ -8613,7 +8444,6 @@ setup_postgresql_db() {
export PG_DB_USER
export PG_DB_PASS
}
-
# ------------------------------------------------------------------------------
# Installs rbenv and ruby-build, installs Ruby and optionally Rails.
#
@@ -8633,31 +8463,8 @@ setup_ruby() {
local RBENV_DIR="$HOME/.rbenv"
local RBENV_BIN="$RBENV_DIR/bin/rbenv"
local PROFILE_FILE="$HOME/.profile"
- local BASH_PROFILE_FILE="$HOME/.bash_profile"
- local BASHRC_FILE="$HOME/.bashrc"
local TMP_DIR=$(mktemp -d)
- # Ensure HOME exists: callers may pass a not-yet-created home (e.g. a service
- # user that is created later in the install), so the profile writes below do
- # not fail on a missing directory.
- mkdir -p "$HOME"
-
- if ! grep -q 'rbenv init' "$PROFILE_FILE" 2>/dev/null; then
- cat <<'EOF' >>"$PROFILE_FILE"
-export PATH="$HOME/.rbenv/bin:$PATH"
-eval "$(rbenv init -)"
-EOF
- fi
- if ! grep -q '.rbenv/shims' "$PROFILE_FILE" 2>/dev/null; then
- echo 'export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"' >>"$PROFILE_FILE"
- fi
- if [[ -f "$BASH_PROFILE_FILE" ]] && ! grep -q '.rbenv/shims' "$BASH_PROFILE_FILE"; then
- echo 'export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"' >>"$BASH_PROFILE_FILE"
- fi
- if [[ -f "$BASHRC_FILE" ]] && ! grep -q '.rbenv/shims' "$BASHRC_FILE"; then
- echo 'export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"' >>"$BASHRC_FILE"
- fi
-
# Get currently installed Ruby version
local CURRENT_RUBY_VERSION=""
if [[ -x "$RBENV_BIN" ]]; then
@@ -9060,16 +8867,6 @@ setup_uv() {
msg_ok "uvx wrapper installed"
fi
- # Install specific Python version if requested (even when uv is already up to date)
- if [[ -n "${PYTHON_VERSION:-}" ]]; then
- msg_info "Installing Python $PYTHON_VERSION via uv"
- $STD uv python install "$PYTHON_VERSION" || {
- msg_error "Failed to install Python $PYTHON_VERSION"
- return 150
- }
- msg_ok "Python $PYTHON_VERSION installed"
- fi
-
return 0
fi
@@ -9272,10 +9069,10 @@ fetch_and_deploy_from_url() {
msg_error "Failed to create temporary directory"
return 252
}
- trap 'rm -rf "$tmpdir" "${unpack_tmp:-}"' RETURN
curl -fsSL -o "$tmpdir/$filename" "$url" || {
msg_error "Download failed: $url"
+ rm -rf "$tmpdir"
return 250
}
@@ -9295,6 +9092,7 @@ fetch_and_deploy_from_url() {
archive_type="tar"
else
msg_error "Unsupported or unknown archive type: $file_desc"
+ rm -rf "$tmpdir"
return 65
fi
@@ -9307,16 +9105,19 @@ fetch_and_deploy_from_url() {
$STD apt install -y "$tmpdir/$filename" || {
$STD dpkg -i "$tmpdir/$filename" || {
_diagnose_deb_failure "$tmpdir/$filename"
+ rm -rf "$tmpdir"
return 100
}
}
+ rm -rf "$tmpdir"
msg_ok "Successfully installed .deb package"
return 0
fi
if [[ -z "$directory" ]]; then
msg_error "Directory parameter is required for archive extraction"
+ rm -rf "$tmpdir"
return 65
fi
@@ -9325,7 +9126,7 @@ fetch_and_deploy_from_url() {
mkdir -p "$directory"
if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
- find "${directory:?}" -mindepth 1 -delete
+ rm -rf "${directory:?}/"*
fi
local unpack_tmp
@@ -9335,11 +9136,13 @@ fetch_and_deploy_from_url() {
ensure_dependencies unzip
unzip -q "$tmpdir/$filename" -d "$unpack_tmp" || {
msg_error "Failed to extract ZIP archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
return 251
}
elif [[ "$archive_type" == "tar" ]]; then
tar --no-same-owner -xf "$tmpdir/$filename" -C "$unpack_tmp" || {
msg_error "Failed to extract TAR archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
return 251
}
fi
@@ -9353,12 +9156,12 @@ fetch_and_deploy_from_url() {
if compgen -G "$inner_dir/*" >/dev/null; then
cp -r "$inner_dir"/* "$directory/" || {
msg_error "Failed to copy contents from $inner_dir to $directory"
- shopt -u dotglob nullglob
+ rm -rf "$tmpdir" "$unpack_tmp"
return 252
}
else
msg_error "Inner directory is empty: $inner_dir"
- shopt -u dotglob nullglob
+ rm -rf "$tmpdir" "$unpack_tmp"
return 252
fi
shopt -u dotglob nullglob
@@ -9367,17 +9170,18 @@ fetch_and_deploy_from_url() {
if compgen -G "$unpack_tmp/*" >/dev/null; then
cp -r "$unpack_tmp"/* "$directory/" || {
msg_error "Failed to copy contents to $directory"
- shopt -u dotglob nullglob
+ rm -rf "$tmpdir" "$unpack_tmp"
return 252
}
else
msg_error "Unpacked archive is empty"
- shopt -u dotglob nullglob
+ rm -rf "$tmpdir" "$unpack_tmp"
return 252
fi
shopt -u dotglob nullglob
fi
+ rm -rf "$tmpdir" "$unpack_tmp"
msg_ok "Successfully deployed archive to $directory"
return 0
}
@@ -9472,7 +9276,6 @@ check_for_gl_release() {
local source="$2"
local pinned_version_in="${3:-}" # optional
local pin_reason="${4:-}" # optional reason shown to user
- local tag_prefix="${5:-}" # optional tag prefix filter (e.g. web-v2)
local app_lc="${app,,}"
local current_file="$HOME/.${app_lc}"
@@ -9549,18 +9352,9 @@ check_for_gl_release() {
rm -f "$gl_check_json"
fi
- if [[ -n "$tag_prefix" ]]; then
- mapfile -t raw_tags < <(jq -r --arg p "$tag_prefix" \
- '.[] | select(.tag_name | startswith($p)) | .tag_name' <<<"$releases_json")
- else
- mapfile -t raw_tags < <(jq -r '.[] | .tag_name' <<<"$releases_json")
- fi
+ mapfile -t raw_tags < <(jq -r '.[] | .tag_name' <<<"$releases_json")
if ((${#raw_tags[@]} == 0)); then
- if [[ -n "$tag_prefix" ]]; then
- msg_error "No releases matching prefix '${tag_prefix}' found for ${app} on GitLab"
- else
- msg_error "No releases found for ${app} on GitLab"
- fi
+ msg_error "No releases found for ${app} on GitLab"
return 250
fi
@@ -9755,7 +9549,6 @@ fetch_and_deploy_gl_release() {
local version="${var_appversion:-${4:-latest}}"
local target="${5:-/opt/$app}"
local asset_pattern="${6:-}"
- local tag_prefix="${7:-}"
if [[ -z "$app" ]]; then
app="${repo##*/}"
@@ -9778,7 +9571,7 @@ fetch_and_deploy_gl_release() {
local gl_rel_json
gl_rel_json=$(mktemp /tmp/tools-gl-rel-XXXXXX) || return 73
- trap 'rm -f "$gl_rel_json"; rm -rf "${tmpdir:-}" "${unpack_tmp:-}"' RETURN
+ trap 'rm -f "$gl_rel_json"' RETURN
local repo_encoded
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
@@ -9787,8 +9580,6 @@ fetch_and_deploy_gl_release() {
local api_url
if [[ "$version" != "latest" ]]; then
api_url="$api_base/$version"
- elif [[ -n "$tag_prefix" ]]; then
- api_url="$api_base?per_page=100&order_by=released_at&sort=desc"
else
api_url="$api_base?per_page=1&order_by=released_at&sort=desc"
fi
@@ -9843,18 +9634,9 @@ fetch_and_deploy_gl_release() {
json=$(<"$gl_rel_json")
if [[ "$version" == "latest" ]]; then
- if [[ -n "$tag_prefix" ]]; then
- json=$(echo "$json" | jq --arg p "$tag_prefix" \
- '[.[] | select(.tag_name | startswith($p))][0] // empty')
- else
- json=$(echo "$json" | jq '.[0] // empty')
- fi
+ json=$(echo "$json" | jq '.[0] // empty')
if [[ -z "$json" || "$json" == "null" ]]; then
- if [[ -n "$tag_prefix" ]]; then
- msg_error "No release matching prefix '${tag_prefix}' found for $repo on GitLab"
- else
- msg_error "No releases found for $repo on GitLab"
- fi
+ msg_error "No releases found for $repo on GitLab"
return 1
fi
fi
@@ -9890,12 +9672,28 @@ fetch_and_deploy_gl_release() {
local direct_tarball_url="https://gitlab.com/$repo/-/archive/$tag_name/${app_lc}-${version_safe}.tar.gz"
filename="${app_lc}-${version_safe}.tar.gz"
- _download_source_tarball "$direct_tarball_url" "$tmpdir/$filename" "${header[@]}" || {
+ curl $download_timeout -fsSL "${header[@]}" -o "$tmpdir/$filename" "$direct_tarball_url" || {
msg_error "Download failed: $direct_tarball_url"
+ rm -rf "$tmpdir"
return 1
}
- _deploy_source_tarball "$tmpdir/$filename" "$target" "$tmpdir" || return 1
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
+ msg_error "Failed to extract tarball"
+ rm -rf "$tmpdir"
+ return 1
+ }
+ local unpack_dir
+ unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
+
+ shopt -s dotglob nullglob
+ cp -r "$unpack_dir"/* "$target/"
+ shopt -u dotglob nullglob
### Binary Mode ###
elif [[ "$mode" == "binary" ]]; then
@@ -9965,12 +9763,14 @@ fetch_and_deploy_gl_release() {
if [[ -z "$url_match" ]]; then
msg_error "No suitable .deb asset found for $app"
+ rm -rf "$tmpdir"
return 1
fi
filename="${url_match##*/}"
curl $download_timeout -fsSL "${header[@]}" -o "$tmpdir/$filename" "$url_match" || {
msg_error "Download failed: $url_match"
+ rm -rf "$tmpdir"
return 1
}
@@ -9981,6 +9781,7 @@ fetch_and_deploy_gl_release() {
DEBIAN_FRONTEND=noninteractive SYSTEMD_OFFLINE=1 $STD apt install -y $dpkg_opts "$tmpdir/$filename" || {
SYSTEMD_OFFLINE=1 $STD dpkg -i "$tmpdir/$filename" || {
_diagnose_deb_failure "$tmpdir/$filename"
+ rm -rf "$tmpdir"
return 1
}
}
@@ -9991,6 +9792,7 @@ fetch_and_deploy_gl_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'prebuild' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 1
}
@@ -10025,18 +9827,75 @@ fetch_and_deploy_gl_release() {
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 1
}
filename="${asset_url##*/}"
curl $download_timeout -fsSL "${header[@]}" -o "$tmpdir/$filename" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 1
}
local unpack_tmp
unpack_tmp=$(mktemp -d)
- _deploy_unpacked_archive "$tmpdir/$filename" "$target" "$unpack_tmp" || return
+ mkdir -p "$target"
+ if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
+ rm -rf "${target:?}/"*
+ fi
+
+ if [[ "$filename" == *.zip ]]; then
+ ensure_dependencies unzip
+ unzip -q "$tmpdir/$filename" -d "$unpack_tmp" || {
+ msg_error "Failed to extract ZIP archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ }
+ elif [[ "$filename" == *.tar.* || "$filename" == *.tgz || "$filename" == *.txz ]]; then
+ tar --no-same-owner -xf "$tmpdir/$filename" -C "$unpack_tmp" || {
+ msg_error "Failed to extract TAR archive"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ }
+ else
+ msg_error "Unsupported archive format: $filename"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ fi
+
+ local top_entries inner_dir
+ top_entries=$(find "$unpack_tmp" -mindepth 1 -maxdepth 1)
+ if [[ "$(echo "$top_entries" | wc -l)" -eq 1 && -d "$top_entries" ]]; then
+ inner_dir="$top_entries"
+ shopt -s dotglob nullglob
+ if compgen -G "$inner_dir/*" >/dev/null; then
+ cp -r "$inner_dir"/* "$target/" || {
+ msg_error "Failed to copy contents from $inner_dir to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ }
+ else
+ msg_error "Inner directory is empty: $inner_dir"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ fi
+ shopt -u dotglob nullglob
+ else
+ shopt -s dotglob nullglob
+ if compgen -G "$unpack_tmp/*" >/dev/null; then
+ cp -r "$unpack_tmp"/* "$target/" || {
+ msg_error "Failed to copy contents to $target"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ }
+ else
+ msg_error "Unpacked archive is empty"
+ rm -rf "$tmpdir" "$unpack_tmp"
+ return 1
+ fi
+ shopt -u dotglob nullglob
+ fi
### Singlefile Mode ###
elif [[ "$mode" == "singlefile" ]]; then
@@ -10044,6 +9903,7 @@ fetch_and_deploy_gl_release() {
pattern="${pattern#\"}"
[[ -z "$pattern" ]] && {
msg_error "Mode 'singlefile' requires 6th parameter (asset filename pattern)"
+ rm -rf "$tmpdir"
return 1
}
@@ -10078,6 +9938,7 @@ fetch_and_deploy_gl_release() {
[[ -z "$asset_url" ]] && {
msg_error "No asset matching '$pattern' found"
+ rm -rf "$tmpdir"
return 1
}
@@ -10090,6 +9951,7 @@ fetch_and_deploy_gl_release() {
curl $download_timeout -fsSL "${header[@]}" -o "$target/$target_file" "$asset_url" || {
msg_error "Download failed: $asset_url"
+ rm -rf "$tmpdir"
return 1
}
@@ -10099,11 +9961,13 @@ fetch_and_deploy_gl_release() {
else
msg_error "Unknown mode: $mode"
+ rm -rf "$tmpdir"
return 1
fi
echo "$version" >"$version_file"
msg_ok "Deployed: $app ($version)"
+ rm -rf "$tmpdir"
}
# ------------------------------------------------------------------------------
diff --git a/tools/pve/cron-update-lxcs.sh b/tools/pve/cron-update-lxcs.sh
index 437c7e472..c97975c44 100644
--- a/tools/pve/cron-update-lxcs.sh
+++ b/tools/pve/cron-update-lxcs.sh
@@ -116,9 +116,6 @@ add() {
# Add container IDs to exclude from updates (comma-separated):
# EXCLUDE=100,101,102
EXCLUDE=
-
-# Healthchecks.io Ping URL (optional)
-# PING_URL=
CONF
ok "Created config ${CONF_FILE}"
fi
@@ -238,11 +235,9 @@ view_cron_config() {
fi
if [[ -f "$CONF_FILE" ]]; then
echo -e " \e[36mConfig file:\e[0m ${CONF_FILE}"
- local excludes ping_url
+ local excludes
excludes=$(grep -oP '^\s*EXCLUDE\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null || true)
- ping_url=$(grep -oP '^\s*PING_URL\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null | tr -d '"' | tr -d "'" || true)
echo -e " \e[36mExcluded:\e[0m ${excludes:-(none)}"
- echo -e " \e[36mPing URL:\e[0m ${ping_url:-(none)}"
echo ""
echo -e " \e[90m--- ${CONF_FILE} ---\e[0m"
cat "$CONF_FILE"
@@ -289,11 +284,9 @@ show_status() {
fi
if [[ -f "$CONF_FILE" ]]; then
- local excludes ping_url
+ local excludes
excludes=$(grep -oP '^\s*EXCLUDE\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null || echo "(none)")
- ping_url=$(grep -oP '^\s*PING_URL\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null | tr -d '"' | tr -d "'" || echo "(none)")
echo -e " \e[36mExcluded:\e[0m ${excludes:-"(none)"}"
- echo -e " \e[36mPing URL:\e[0m ${ping_url:-"(none)"}"
fi
if [[ -f "$LOG_FILE" ]]; then
diff --git a/tools/pve/update-lxcs-cron.sh b/tools/pve/update-lxcs-cron.sh
index 0e021944a..d7abc4cae 100644
--- a/tools/pve/update-lxcs-cron.sh
+++ b/tools/pve/update-lxcs-cron.sh
@@ -11,15 +11,14 @@
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
CONF_FILE="/etc/update-lxcs.conf"
-LOG_FILE="/var/log/update-lxcs-cron.log"
-PING_URL=""
+
+echo -e "\n $(date)"
# Collect excluded containers from arguments
excluded_containers=("$@")
-# Merge exclusions and healthchecks URL from config file if it exists
+# Merge exclusions from config file if it exists
if [[ -f "$CONF_FILE" ]]; then
- PING_URL=$(grep -oP '^\s*PING_URL\s*=\s*\K.+' "$CONF_FILE" 2>/dev/null | tr -d '"' | tr -d "'" || true)
conf_exclude=$(grep -oP '^\s*EXCLUDE\s*=\s*\K[0-9,]+' "$CONF_FILE" 2>/dev/null || true)
IFS=',' read -ra conf_ids <<<"$conf_exclude"
for id in "${conf_ids[@]}"; do
@@ -28,17 +27,6 @@ if [[ -f "$CONF_FILE" ]]; then
done
fi
-# Overwrite logfile on each run when healthchecks is used
-if [[ -n "$PING_URL" ]]; then
- true > "$LOG_FILE"
-fi
-
-if [[ -n "$PING_URL" ]]; then
- curl -fsS -m 10 --retry 5 "${PING_URL}/start" -o /dev/null 2>/dev/null || true
-fi
-
-echo -e "\n $(date)"
-
function update_container() {
local container=$1
local name
@@ -50,36 +38,12 @@ function update_container() {
alpine) pct exec "$container" -- ash -c "apk -U upgrade" ;;
archlinux) pct exec "$container" -- bash -c "pacman -Syyu --noconfirm" ;;
fedora | rocky | centos | alma) pct exec "$container" -- bash -c "dnf -y update && dnf -y upgrade" ;;
- ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update; DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::='--force-confold' dist-upgrade -y; status=\$?; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED || true; exit \$status" ;;
+ ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::='--force-confold' dist-upgrade -y; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED" ;;
opensuse) pct exec "$container" -- bash -c "zypper ref && zypper --non-interactive dup" ;;
*) echo " [Warn] Unknown OS type '$os' for container $container, skipping" ;;
esac
}
-update_status=0
-
-# Define exit handler to send healthchecks.io status (with logfile on failure/success)
-function exit_handler() {
- local exit_code=$?
- if [[ -n "$PING_URL" ]]; then
- sync
- if [[ $exit_code -ne 0 || $update_status -ne 0 ]]; then
- if [[ -f "$LOG_FILE" ]]; then
- curl -fsS -m 10 --retry 5 --data-binary @"$LOG_FILE" "${PING_URL}/fail" -o /dev/null 2>/dev/null || true
- else
- curl -fsS -m 10 --retry 5 "${PING_URL}/fail" -o /dev/null 2>/dev/null || true
- fi
- else
- if [[ -f "$LOG_FILE" ]]; then
- curl -fsS -m 10 --retry 5 --data-binary @"$LOG_FILE" "$PING_URL" -o /dev/null 2>/dev/null || true
- else
- curl -fsS -m 10 --retry 5 "$PING_URL" -o /dev/null 2>/dev/null || true
- fi
- fi
- fi
-}
-trap exit_handler EXIT
-
for container in $(pct list | awk '{if(NR>1) print $1}'); do
excluded=false
for excluded_container in "${excluded_containers[@]}"; do
@@ -101,7 +65,7 @@ for container in $(pct list | awk '{if(NR>1) print $1}'); do
echo -e "[Info] Starting $container"
pct start "$container"
sleep 5
- update_container "$container" || { echo " [Error] Update failed for $container"; update_status=1; }
+ update_container "$container" || echo " [Error] Update failed for $container"
# check if patchmon agent is present in container and run a report if found
if pct exec "$container" -- [ -e "/usr/local/bin/patchmon-agent" ]; then
echo -e "${BL}[Info]${GN} patchmon-agent found in ${BL} $container ${CL}, triggering report. \n"
@@ -110,7 +74,7 @@ for container in $(pct list | awk '{if(NR>1) print $1}'); do
echo -e "[Info] Shutting down $container"
pct shutdown "$container" --timeout 60 &
elif [ "$status" == "status: running" ]; then
- update_container "$container" || { echo " [Error] Update failed for $container"; update_status=1; }
+ update_container "$container" || echo " [Error] Update failed for $container"
# check if patchmon agent is present in container and run a report if found
if pct exec "$container" -- [ -e "/usr/local/bin/patchmon-agent" ]; then
echo -e "${BL}[Info]${GN} patchmon-agent found in ${BL} $container ${CL}, triggering report. \n"
diff --git a/tools/pve/update-lxcs.sh b/tools/pve/update-lxcs.sh
index e083a4fc2..52e9d2528 100644
--- a/tools/pve/update-lxcs.sh
+++ b/tools/pve/update-lxcs.sh
@@ -78,7 +78,7 @@ function update_container() {
alpine) pct exec "$container" -- ash -c "apk -U upgrade" ;;
archlinux) pct exec "$container" -- bash -c "pacman -Syyu --noconfirm" ;;
fedora | rocky | centos | alma) pct exec "$container" -- bash -c "dnf -y update && dnf -y upgrade" ;;
- ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update 2>/dev/null | grep 'packages.*upgraded'; apt list --upgradable 2>/dev/null | cat && apt-get -yq dist-upgrade 2>&1; apt-get -yq autoremove 2>&1; apt-get -yq autoclean 2>&1; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED || true" ;;
+ ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update 2>/dev/null | grep 'packages.*upgraded'; apt list --upgradable 2>/dev/null | cat && apt-get -yq dist-upgrade 2>&1; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED || true" ;;
opensuse) pct exec "$container" -- bash -c "zypper ref && zypper --non-interactive dup" ;;
esac
}
diff --git a/vm/haos-vm.sh b/vm/haos-vm.sh
index df5189614..85d582170 100644
--- a/vm/haos-vm.sh
+++ b/vm/haos-vm.sh
@@ -475,7 +475,7 @@ function advanced_settings() {
done
while true; do
- if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan (leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
+ if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VLAN1" ]; then
VLAN1="Default"
VLAN=""
diff --git a/vm/opnsense-vm.sh b/vm/opnsense-vm.sh
index 4d15f25be..3b18e3b74 100644
--- a/vm/opnsense-vm.sh
+++ b/vm/opnsense-vm.sh
@@ -24,7 +24,7 @@ RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
METHOD=""
NSAPP="opnsense-vm"
var_os="opnsense"
-var_version="26.7"
+var_version="26.1"
#
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
GEN_MAC_LAN=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
@@ -814,7 +814,7 @@ if [ -n "$WAN_BRG" ]; then
msg_ok "WAN interface added"
sleep 5 # Brief pause after adding network interface
fi
-send_line_to_vm "sh ./opnsense-bootstrap.sh.in -y -f -r 26.7"
+send_line_to_vm "sh ./opnsense-bootstrap.sh.in -y -f -r 26.1"
msg_ok "OPNsense VM is being installed, do not close the terminal, or the installation will fail."
#We need to wait for the OPNsense build proccess to finish, this takes a few minutes
sleep 1000