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 @@ - _ __ __ - / | / /__ _ __/ /____ _________ ___ - / |/ / _ \| |/_/ __/ _ \/ ___/ __ `__ \ - / /| / __/> "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