Compare commits

..

71 Commits

Author SHA1 Message Date
CanbiZ (MickLesk) d0634b0ca8 SnapOtter: refactor deployment and installation process
Updated the SnapOtter deployment process to use prebuilt releases and modified the installation steps for Python and virtual environment setup.
2026-07-15 11:07:01 +02:00
community-scripts-pr-app[bot] 2afea1239c Update CHANGELOG.md (#15789)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 20:55:21 +00:00
CanbiZ (MickLesk) 07e31eb5bc Pangolin: Bump to 1.20.0 | BREAKING: Switch to PostgreSQL (#15682)
* Pangolin: Bump to 1.20.0 and harden SQLite migrations

Bump the default Pangolin version to 1.20.0 in both CT and install scripts. Update the CT upgrade path to validate required 1.20.0 schema objects, clear stale versionMigrations markers when needed, retry migrations once, and abort with a clear error if the schema is still incomplete to avoid a broken runtime.

* extend migration check...

* another try...

* bump pangolin to PSQL

* remove migration paths

* remove old migrations

* use create_backup and restore_backup

* Block Pangolin SQLite upgrades

Update the Pangolin CT upgrade path to fail fast when PostgreSQL is not installed. The script now explains that upgrades to Pangolin 1.20.0+ require PostgreSQL and that SQLite data cannot be migrated automatically.

* fix env

* Update pangolin.sh

* Update pangolin-install.sh
2026-07-14 22:54:55 +02:00
community-scripts-pr-app[bot] 80c4b04d83 Update CHANGELOG.md (#15788)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 20:38:53 +00:00
CanbiZ (MickLesk) ed29bb6f62 AFFiNE: Pin to v0.26.3 (#15782)
* AFFiNE: Pin to v0.26.3

* Update GitHub release version to v0.26.3
2026-07-14 22:38:24 +02:00
community-scripts-pr-app[bot] a5b839f91f Update CHANGELOG.md (#15781)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:16:30 +00:00
push-app-to-main[bot] d4d482746b Add grav (ct) (#15773)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-07-14 14:16:10 +02:00
community-scripts-pr-app[bot] 2bffa47924 Update CHANGELOG.md (#15780)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:16:01 +00:00
push-app-to-main[bot] 108c9dcf43 Add yuvomi (ct) (#15772)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-07-14 14:15:32 +02:00
community-scripts-pr-app[bot] 0f37abff3c Update CHANGELOG.md (#15779)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:14:44 +00:00
Michel Roegl-Brunner 670d972cc1 fix(wanderer): clean deploy and install plugins for v0.20.0 update (#15759)
Use CLEAN_INSTALL with create_backup/restore_backup so stale v0.19.x source files no longer break go build after the integrations migration. Also set up the plugins directory and install official WASM bundles.
2026-07-14 14:14:20 +02:00
community-scripts-pr-app[bot] 9f8bc4b03d Update CHANGELOG.md (#15778)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:08:38 +00:00
CanbiZ (MickLesk) 817ee347c7 Bump OpenCloud version to v7.2.2 (#15769)
* Bump OpenCloud release version to v7.2.2

* Update OpenCloud version to v7.2.2
2026-07-14 22:08:14 +10:00
community-scripts-pr-app[bot] bb4e35f988 Update CHANGELOG.md (#15777)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:02:17 +00:00
community-scripts-pr-app[bot] 254e720b4f Update CHANGELOG.md (#15776)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:01:44 +00:00
Michel Roegl-Brunner 9055f4b34e fix(lychee): preserve uploads and ownership during update (#15768)
The update script wiped public/uploads and did not re-apply www-data
ownership, causing HTTP 500 after successful updates. Align with upstream
upgrade steps and sibling Laravel scripts by backing up uploads/dist,
restarting PHP-FPM, running full artisan cache cycle, and adding verbose
diagnostics.

Fixes #15763
2026-07-14 22:01:40 +10:00
Michel Roegl-Brunner 3f5453b609 FileFlows: Handle update API 401, force update, and Node install (#15766)
* fix(fileflows): handle update API failures and fix Node install

Server updates no longer abort on 401 or unreachable API; users can force deploy when security is enabled or the app is down. Node installs now pass --server during systemd setup, and Node updates skip the server-only API.

* Update fileflows.sh
2026-07-14 22:01:16 +10:00
community-scripts-pr-app[bot] e812206116 Update CHANGELOG.md (#15775)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 12:00:40 +00:00
Michel Roegl-Brunner 7f430e15bb feat(silverbullet): add optional Runtime API install via Chromium (#15761)
Adds an install-time prompt to optionally enable Silverbullet's Runtime API by installing Chromium and configuring SB_CHROME_PATH / SB_CHROME_DATA_DIR.
2026-07-14 22:00:17 +10:00
community-scripts-pr-app[bot] 9c586b94ab Update CHANGELOG.md (#15774)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 11:58:44 +00:00
Michel Roegl-Brunner ab3c9be482 fix(birdnet-go): match new upstream release asset naming (#15758)
Upstream BirdNET-Go releases now suffix tarball names with the release date (e.g. birdnet-go-linux-amd64-20260713.tar.gz). Use a wildcard pattern so install and update can fetch the latest release without falling back to older nightlies.

Fixes #15753
2026-07-14 21:58:22 +10:00
community-scripts-pr-app[bot] 103b420e30 Update CHANGELOG.md (#15771)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 11:08:23 +00:00
CanbiZ (MickLesk) c039ab2e62 Refactor input and checkbox fields for repository stars 2026-07-14 12:45:49 +02:00
CanbiZ (MickLesk) 63f219f14f Revise project eligibility criteria in request template
Updated eligibility requirements for project requests in the discussion template, clarifying the criteria for self-hosting, repository stars, and project age.
2026-07-14 12:44:19 +02:00
community-scripts-pr-app[bot] 09ec7b3203 Update CHANGELOG.md (#15765)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 10:02:33 +00:00
Michel Roegl-Brunner 55ab97a020 Revert "fix(fileflows): handle update API failures and fix Node install (#14858)" (#15764)
This reverts commit 171b954c7c.
2026-07-14 12:02:10 +02:00
community-scripts-pr-app[bot] b7a002cae4 Update CHANGELOG.md (#15762)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 10:00:47 +00:00
Michel Roegl-Brunner 171b954c7c fix(fileflows): handle update API failures and fix Node install (#14858)
Server updates no longer abort on 401 or unreachable API; users can force deploy when security is enabled or the app is down. Node installs now pass --server during systemd setup, and Node updates skip the server-only API.
2026-07-14 12:00:22 +02:00
community-scripts-pr-app[bot] 6f76cc043e Update CHANGELOG.md (#15756)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-14 07:32:54 +00:00
Chris 5d57c328fb [Upstream Fix] Immich: Fix loader priority (#15755) 2026-07-14 09:32:29 +02:00
community-scripts-pr-app[bot] da62724407 Update CHANGELOG.md (#15749)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 15:41:02 +00:00
push-app-to-main[bot] dbe2c9eb97 Add leafwiki (ct) (#15748)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-07-13 17:39:10 +02:00
community-scripts-pr-app[bot] 3c5a848d7d Update CHANGELOG.md (#15747)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 13:10:47 +00:00
Michel Roegl-Brunner 1e3d0dedb3 Change sign-in URL to admin URL in affine.sh (#15741) 2026-07-13 23:09:56 +10:00
CanbiZ (MickLesk) bcaadc4dbd typo 2026-07-13 14:58:23 +02:00
community-scripts-pr-app[bot] 666bdbd8c8 Update CHANGELOG.md (#15742)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 10:00:14 +00:00
mnavon 7596b95517 immich: use actual PostgreSQL version for VectorChord package lookup (#15705)
* immich: use actual PostgreSQL version for VectorChord package lookup

* fix: update PostgreSQL version variable for VectorChord package deployment
2026-07-13 11:59:52 +02:00
community-scripts-pr-app[bot] 1521e131b5 Update CHANGELOG.md (#15740)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:56:44 +00:00
Michel Roegl-Brunner 734bb75b12 fix storyteller release selection for multi-stream tags (#15736)
Add optional tag prefix filtering to GitHub/GitLab release helpers and use web-v2 for Storyteller install/update so latest non-web tags no longer break deployment.
2026-07-13 11:56:12 +02:00
community-scripts-pr-app[bot] d6d8d20c76 Update CHANGELOG.md (#15739)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:38:01 +00:00
CanbiZ (MickLesk) 649e66ed2b tools.func: some improvements (sql injection / command injection / guard) (#15661)
* Update tools.func

- Add _TOOLS_FUNC_LOADED guard to prevent double-sourcing
- Remove duplicate is_alpine() (core.func version is more robust)
- Fix end_timer: now actually outputs duration (was silent)
- Fix SQL injection in setup_mariadb_db: escape single quotes in identifiers
- Fix SQL injection in setup_postgresql_db: escape single quotes in identifiers
- Fix sed injection in edit_yaml_config: escape | and & in value
- Fix command injection in curl_with_retry: use array instead of string eval
- Fix command injection in curl_api_with_retry: use array instead of string eval

* Update misc/tools.func

Co-authored-by: Sam Heinz <sam@samheinz.com>

---------

Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-07-13 11:37:39 +02:00
community-scripts-pr-app[bot] 81bb9c7d71 Update CHANGELOG.md (#15737)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:32:19 +00:00
CanbiZ (MickLesk) ca082aedf0 Docmost: Fix update procedure (#15732)
Updated messages for configuring and starting the Docmost service.
2026-07-13 11:31:53 +02:00
community-scripts-pr-app[bot] 1e7667e5f8 Update CHANGELOG.md (#15735)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:12:36 +00:00
TowyTowy f828e629b5 fix(hyperion): keep service running after container reboot (#15653)
* fix(hyperion): keep service running after container reboot

The packaged hyperion@.service declares "Requisite=network.target" but is
not ordered After=network.target. Inside an LXC the unit's start job can be
evaluated before network.target is active, and because Requisite= is stricter
than Requires= (it does not pull the unit in or wait for it) the job fails
with "Dependency failed", so Hyperion does not start after a reboot.

Add a systemd drop-in that clears Requisite=; ordering is still provided by
the base unit's Wants=/After=network-online.target.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix Hyperion service startup issue in LXC

Remove Requisite from Hyperion service to ensure it starts correctly in LXC environments.

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-07-13 11:12:10 +02:00
community-scripts-pr-app[bot] 4a98e86db1 Update CHANGELOG.md (#15734)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:11:36 +00:00
community-scripts-pr-app[bot] 37b5242c21 Update CHANGELOG.md (#15733)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:11:16 +00:00
Michel Roegl-Brunner a1333222a8 fix(shinobi): remove obsolete --unsafe-perm npm flag (#15730)
Shinobi installs fail on Node.js 22 because npm 10 no longer accepts the
--unsafe-perm CLI flag during npm install.
2026-07-13 11:11:08 +02:00
Michel Roegl-Brunner 12949bce6c fix(build.func): parse script status without jq dependency (#15729)
Replace jq-based PocketBase status parsing with sed/grep so disabled and deleted script checks work on hosts that do not have jq installed yet.
2026-07-13 11:10:49 +02:00
community-scripts-pr-app[bot] fae0aacf6d Update CHANGELOG.md (#15731)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 09:05:39 +00:00
Tobias fd20ed1bfc reitti: update to v5 (#15635) 2026-07-13 11:05:11 +02:00
community-scripts-pr-app[bot] eb3fb749df Update CHANGELOG.md (#15727)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-12 21:22:59 +00:00
push-app-to-main[bot] f7fdf419b1 AFFiNE (#15690) 2026-07-12 23:22:39 +02:00
community-scripts-pr-app[bot] 0a7bd0f37e Update CHANGELOG.md (#15724)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-12 16:24:42 +00:00
Copilot 48483c63b8 fix(immich): correct Python indentation error in ct/immich.sh heredoc patch (#15723)
* Initial plan

* fix: correct Python indentation in immich heredoc patch (ct/immich.sh)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-12 18:24:19 +02:00
community-scripts-pr-app[bot] 962c040f44 Update CHANGELOG.md (#15721)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-12 15:49:09 +00:00
Chris c0b2c906fa Immich: Bump version to 3.0.2 (#15668)
* Immich: Bump version to 3.0.2

* Bump vchord to 1.1.1

* Add MickLesk HEIC patch
2026-07-12 17:48:43 +02:00
community-scripts-pr-app[bot] 96100474cc Update CHANGELOG.md (#15715)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-12 00:18:12 +00:00
community-scripts-pr-app[bot] 76335cefe8 Archive old changelog entries (#15714)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-12 00:17:46 +00:00
community-scripts-pr-app[bot] 8fbb4b1988 Update CHANGELOG.md (#15712)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 20:15:36 +00:00
TowyTowy c481c3e24e fix(fileflows): install .NET 10 ASP.NET Core Runtime to match current release (#15702)
* fix(fileflows): install .NET 10 ASP.NET Core Runtime to match current release

FileFlows now ships its server/node binaries targeting .NET 10
(Microsoft.NETCore.App 10.0.0), but the install script still installs the
ASP.NET Core Runtime 8.0. On a fresh install the app therefore cannot start:

  You must install or update .NET to run this application.
  Framework: 'Microsoft.NETCore.App', version '10.0.0' (x64)
  The following frameworks were found:
    8.0.28 at [/usr/share/dotnet/shared/Microsoft.NETCore.App]

so "dotnet FileFlows.Server.dll --systemd install" fails with exit code 150
(service failed to start) and the container aborts (issue #15686).

Bump the runtime to 10.0 on both branches: aspnetcore-runtime-10.0 from
packages.microsoft.com on amd64 (the same repo and package already used by
igotify, rdtclient and technitiumdns) and dotnet-install --channel 10.0 on
arm64.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(fileflows): ensure current .NET runtime on update too

An existing install set up under an older .NET (e.g. aspnetcore-runtime-8.0)
would download a newer FileFlows on update but keep the old runtime, failing to
start with the same framework-not-found error. Mirror the runtime handling used
by technitiumdns/rdtclient in update_script.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 22:15:12 +02:00
community-scripts-pr-app[bot] dcd1eefdd4 Update CHANGELOG.md (#15709)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 18:07:32 +00:00
TowyTowy f1b2bd0486 fix(adventurelog): allow pnpm build scripts so install/update doesn't abort (#15681)
AdventureLog's frontend install runs a bare `pnpm i`. On pnpm v10+, build
scripts of dependencies (esbuild, es5-ext, svelte-preprocess) are ignored by
default and pnpm aborts with ERR_PNPM_IGNORED_BUILDS (exit 1), so the install
never reaches `pnpm build`. The shipped frontend/pnpm-workspace.yaml already
pins esbuild, so those builds are expected to run.

Enable the builds for this app only by appending `dangerouslyAllowAllBuilds:
true` to the frontend's pnpm-workspace.yaml before `pnpm i`, in both the install
and update paths. The change is guarded so it is not duplicated on re-run, and
it is scoped to AdventureLog (which ships no onlyBuiltDependencies) to avoid the
global config conflict that a repo-wide setting would cause.

Fixes #15670

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 20:07:05 +02:00
community-scripts-pr-app[bot] 42f6b3ccdd Update CHANGELOG.md (#15708)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 18:00:59 +00:00
community-scripts-pr-app[bot] ed9c80f805 Update CHANGELOG.md (#15707)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 18:00:51 +00:00
push-app-to-main[bot] 0906341e95 LocalAGI (#15687)
* Add localagi (ct)

* Refactor localagi.sh for better readability

Removed unnecessary blank lines and improved script readability.

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-07-11 20:00:36 +02:00
Slaviša Arežina 618d578c35 [tools.func]: Add function to handle deployment via GitLab release tags (#15641)
* Update CHANGELOG.md (#15631)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Update CHANGELOG.md (#15631)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Update CHANGELOG.md (#15631)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* add gl tag handling funcs

---------

Co-authored-by: community-scripts-pr-app[bot] <189241966+community-scripts-pr-app[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 20:00:29 +02:00
community-scripts-pr-app[bot] f137f8c894 Update CHANGELOG.md (#15699)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 08:49:21 +00:00
pumrum 98bedb6ccd Fix spacing on VLAN Input Box in haos-vm.sh (#15696) 2026-07-11 10:48:55 +02:00
community-scripts-pr-app[bot] b958252441 Update CHANGELOG.md (#15692)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-10 18:48:25 +00:00
wollew 92c4fb45a9 Adapt to new artifact filename format for pocket id (#15689)
* Adapt to new artifact filename format for pocket id

* adapt pocket id install to new artifact filename format as well
2026-07-10 20:47:58 +02:00
50 changed files with 1798 additions and 448 deletions
+40 -7
View File
@@ -12,13 +12,17 @@ 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. 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: General requirements:
- The application should be self-hosted. - The application must be self-hosted.
- The project should have an official public source repository. - The project must have an official public source repository.
- The project should provide official releases, tags, or release tarballs. - The project must provide official releases, tags, or release tarballs.
- The project should be actively maintained. - The project must be actively maintained.
- The project should generally have at least 1,000 stars or a comparable public adoption signal. - The official source repository must have at least 1,000 stars.
- The latest official release or tag should not be older than 6 months. - The latest official release or tag must not be older than 6 months.
- The project itself should be at least 6 months old. - 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.
- type: input - type: input
id: application-name id: application-name
@@ -47,6 +51,35 @@ body:
validations: validations:
required: true 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 - type: textarea
id: app-description id: app-description
attributes: attributes:
+91
View File
@@ -1,3 +1,94 @@
## 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 ## 2026-07-04
### 🚀 Updated Scripts ### 🚀 Updated Scripts
+102 -133
View File
@@ -74,6 +74,9 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
@@ -87,7 +90,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details> <details>
<summary><h4>July (4 entries)</h4></summary> <summary><h4>July (11 entries)</h4></summary>
[View July 2026 Changelog](.github/changelogs/2026/07.md) [View July 2026 Changelog](.github/changelogs/2026/07.md)
@@ -499,6 +502,102 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details> </details>
## 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 ## 2026-07-10
### 🆕 New Scripts ### 🆕 New Scripts
@@ -509,6 +608,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### 🐞 Bug Fixes - #### 🐞 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)) - 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)) - Endurain: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15674](https://github.com/community-scripts/ProxmoxVE/pull/15674))
@@ -1082,135 +1182,4 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### ✨ New Features - #### ✨ New Features
- [core] Implement backup and restore functions [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15067](https://github.com/community-scripts/ProxmoxVE/pull/15067)) - [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))
+1
View File
@@ -60,6 +60,7 @@ function update_script() {
$STD .venv/bin/python -m manage migrate $STD .venv/bin/python -m manage migrate
cd /opt/adventurelog/frontend cd /opt/adventurelog/frontend
grep -q "^dangerouslyAllowAllBuilds:" ./pnpm-workspace.yaml 2>/dev/null || echo "dangerouslyAllowAllBuilds: true" >>./pnpm-workspace.yaml
$STD pnpm i $STD pnpm i
$STD pnpm build $STD pnpm build
msg_ok "Updated AdventureLog" msg_ok "Updated AdventureLog"
+128
View File
@@ -0,0 +1,128 @@
#!/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.26.3"
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"
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)"
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)
$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"
# Force Turbo to run sequentially
mkdir -p /opt/affine/.turbo
cat <<TURBO >/opt/affine/.turbo/config.json
{
"concurrency": 1
}
TURBO
$STD corepack enable
$STD corepack prepare yarn@4.12.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}"
+1 -1
View File
@@ -37,7 +37,7 @@ function update_script() {
systemctl stop birdnet systemctl stop birdnet
msg_ok "Stopped Service" 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" msg_info "Deploying Binary"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
+3 -2
View File
@@ -39,7 +39,6 @@ function update_script() {
create_backup /opt/docmost/.env \ create_backup /opt/docmost/.env \
/opt/docmost/data /opt/docmost/data
fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball" fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball"
restore_backup restore_backup
@@ -54,9 +53,11 @@ function update_script() {
sed -i '/^@Module({$/i @Global()' /opt/docmost/apps/server/src/core/core.module.ts sed -i '/^@Module({$/i @Global()' /opt/docmost/apps/server/src/core/core.module.ts
fi fi
msg_info "Configuring Docmost"
cd /opt/docmost
$STD pnpm install --force $STD pnpm install --force
$STD pnpm build $STD pnpm build
msg_ok "Updated ${APP}" msg_ok "Configured Docmost"
msg_info "Starting Service" msg_info "Starting Service"
systemctl start docmost systemctl start docmost
+73 -18
View File
@@ -31,28 +31,83 @@ function update_script() {
exit exit
fi fi
update_available=$(curl -fsSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable) local proceed=false
if [[ "${update_available}" == "true" ]]; then
msg_info "Stopping Service"
systemctl --all stop 'fileflows*'
msg_info "Stopped Service"
msg_info "Creating Backup" if systemctl list-unit-files 'fileflows.service' --no-legend 2>/dev/null | grep -q '^fileflows\.service'; then
ls /opt/*.tar.gz &>/dev/null && rm -f /opt/*.tar.gz tmp=$(mktemp)
backup_filename="/opt/${APP}_backup_$(date +%F).tar.gz" 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"
tar -czf "$backup_filename" -C /opt/fileflows Data if [[ "$http_code" == "200" ]]; then
msg_ok "Backup Created" update_available=$(jq -r '.UpdateAvailable // false' "$tmp" 2>/dev/null)
rm -f "$tmp"
fetch_and_deploy_from_url "https://fileflows.com/downloads/zip" "/opt/fileflows" if [[ "${update_available}" == "true" ]]; then
proceed=true
msg_info "Starting Service" else
systemctl --all start 'fileflows*' msg_ok "No update required. ${APP} is already at latest version"
msg_ok "Started Service" exit
msg_ok "Updated successfully!" 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
else else
msg_ok "No update required. ${APP} is already at latest version" proceed=true
fi 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 exit
} }
+54
View File
@@ -0,0 +1,54 @@
#!/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}"
+6
View File
@@ -0,0 +1,6 @@
___ _____________ _ ________
/ | / ____/ ____(_) | / / ____/
/ /| | / /_ / /_ / / |/ / __/
/ ___ |/ __/ / __/ / / /| / /___
/_/ |_/_/ /_/ /_/_/ |_/_____/
+6
View File
@@ -0,0 +1,6 @@
______
/ ____/________ __ __
/ / __/ ___/ __ `/ | / /
/ /_/ / / / /_/ /| |/ /
\____/_/ \__,_/ |___/
+6
View File
@@ -0,0 +1,6 @@
__ _____ ___ __ _
/ / ___ ____ _/ __/ | / (_) /__(_)
/ / / _ \/ __ `/ /_ | | /| / / / //_/ /
/ /___/ __/ /_/ / __/ | |/ |/ / / ,< / /
/_____/\___/\__,_/_/ |__/|__/_/_/|_/_/
+6
View File
@@ -0,0 +1,6 @@
__ _____ __________
/ / ____ _________ _/ / | / ____/ _/
/ / / __ \/ ___/ __ `/ / /| |/ / __ / /
/ /___/ /_/ / /__/ /_/ / / ___ / /_/ // /
/_____/\____/\___/\__,_/_/_/ |_\____/___/
-6
View File
@@ -1,6 +0,0 @@
_ __ __
/ | / /__ _ __/ /____ _________ ___
/ |/ / _ \| |/_/ __/ _ \/ ___/ __ `__ \
/ /| / __/> </ /_/ __/ / / / / / / /
/_/ |_/\___/_/|_|\__/\___/_/ /_/ /_/ /_/
+6
View File
@@ -0,0 +1,6 @@
__ __ _
\ \/ /_ ___ ______ ____ ___ (_)
\ / / / / | / / __ \/ __ `__ \/ /
/ / /_/ /| |/ / /_/ / / / / / / /
/_/\__,_/ |___/\____/_/ /_/ /_/_/
+27 -3
View File
@@ -110,7 +110,7 @@ EOF
msg_ok "Image-processing libraries up to date" msg_ok "Image-processing libraries up to date"
fi fi
RELEASE="v3.0.1" RELEASE="v3.0.2"
if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
if [[ $(cat ~/.immich) > "2.5.1" ]]; then if [[ $(cat ~/.immich) > "2.5.1" ]]; then
msg_info "Enabling Maintenance Mode" msg_info "Enabling Maintenance Mode"
@@ -124,7 +124,9 @@ EOF
systemctl stop immich-web systemctl stop immich-web
systemctl stop immich-ml systemctl stop immich-ml
msg_ok "Stopped Services" msg_ok "Stopped Services"
VCHORD_RELEASE="1.0.0" VCHORD_RELEASE="1.1.1"
PG_VERSION=$(ls /etc/postgresql/ 2>/dev/null | sort -V | tail -1)
PG_VERSION=${PG_VERSION:-16}
[[ -f ~/.vchord_version ]] && mv ~/.vchord_version ~/.vectorchord [[ -f ~/.vchord_version ]] && mv ~/.vchord_version ~/.vectorchord
if check_for_gh_release "VectorChord" "tensorchord/VectorChord" "${VCHORD_RELEASE}" "updated together with Immich after testing"; then 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 # dead tuples in smart_search/face_search make the REINDEX below fail with
@@ -132,7 +134,7 @@ EOF
# while still on the old extension version, a post-upgrade vacuum errors instead # 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) smart_search;"
$STD sudo -u postgres psql -d immich -c "VACUUM (ANALYZE) face_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-16-vchord_*_$(arch_resolve).deb" fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-${PG_VERSION}-vchord_*_$(arch_resolve).deb"
systemctl restart postgresql 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 vector UPDATE;"
$STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;" $STD sudo -u postgres psql -d immich -c "ALTER EXTENSION vchord UPDATE;"
@@ -328,6 +330,27 @@ EOF
systemctl daemon-reload systemctl daemon-reload
fi 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 excluding upload dir contents (may be a mount with restricted permissions)
chown immich:immich "$INSTALL_DIR" chown immich:immich "$INSTALL_DIR"
find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} + find "$INSTALL_DIR" -maxdepth 1 -mindepth 1 ! -name upload -exec chown -R immich:immich {} +
@@ -478,6 +501,7 @@ function compile_libvips() {
$STD git clone https://github.com/libvips/libvips.git "$SOURCE" $STD git clone https://github.com/libvips/libvips.git "$SOURCE"
cd "$SOURCE" cd "$SOURCE"
$STD git reset --hard "$LIBVIPS_REVISION" $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 $STD meson setup build --buildtype=release --libdir=lib -Dintrospection=disabled -Dtiff=disabled
cd build cd build
$STD ninja install $STD ninja install
+57
View File
@@ -0,0 +1,57 @@
#!/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}"
+67
View File
@@ -0,0 +1,67 @@
#!/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}"
+18 -13
View File
@@ -31,33 +31,38 @@ function update_script() {
fi fi
if check_for_gh_release "lychee" "LycheeOrg/Lychee"; then if check_for_gh_release "lychee" "LycheeOrg/Lychee"; then
PHP_VER=$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')
msg_info "Stopping Services" msg_info "Stopping Services"
systemctl stop caddy systemctl stop caddy php${PHP_VER}-fpm
msg_ok "Stopped Services" msg_ok "Stopped Services"
msg_info "Backing up Data" create_backup /opt/lychee/.env \
cp /opt/lychee/.env /opt/lychee.env.bak /opt/lychee/storage \
cp -r /opt/lychee/storage /opt/lychee_storage_backup /opt/lychee/public/uploads \
msg_ok "Backed up Data" /opt/lychee/public/dist
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "lychee" "LycheeOrg/Lychee" "prebuild" "latest" "/opt/lychee" "Lychee.zip" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "lychee" "LycheeOrg/Lychee" "prebuild" "latest" "/opt/lychee" "Lychee.zip"
msg_info "Restoring Data" restore_backup
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" msg_info "Updating Application"
cd /opt/lychee cd /opt/lychee
$STD php artisan migrate --force $STD php artisan migrate --force
$STD php artisan config:clear
$STD php artisan cache:clear
$STD php artisan optimize:clear $STD php artisan optimize:clear
chmod -R 775 /opt/lychee/storage /opt/lychee/bootstrap/cache $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
msg_ok "Updated Application" msg_ok "Updated Application"
msg_info "Starting Services" msg_info "Starting Services"
systemctl start caddy systemctl start caddy php${PHP_VER}-fpm
msg_ok "Started Services" msg_ok "Started Services"
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
fi fi
-66
View File
@@ -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}"
+1 -1
View File
@@ -30,7 +30,7 @@ function update_script() {
exit exit
fi fi
RELEASE="v7.2.1" RELEASE="v7.2.2"
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 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" msg_info "Stopping services"
systemctl stop opencloud opencloud-wopi systemctl stop opencloud opencloud-wopi
+18 -21
View File
@@ -6,7 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin # Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin
APP="Pangolin" APP="Pangolin"
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.4}" PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.20.0}"
var_tags="${var_tags:-proxy}" var_tags="${var_tags:-proxy}"
var_cpu="${var_cpu:-2}" var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}" var_ram="${var_ram:-4096}"
@@ -33,6 +33,15 @@ function update_script() {
ensure_dependencies build-essential python3 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 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=<tag>' and re-run update. If it breaks, please open an issue at https://github.com/community-scripts/ProxmoxVE/issues with the error log."; then 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=<tag>' and re-run update. If it breaks, please open an issue at https://github.com/community-scripts/ProxmoxVE/issues with the error log."; then
@@ -41,13 +50,8 @@ function update_script() {
systemctl stop gerbil systemctl stop gerbil
msg_info "Service stopped" msg_info "Service stopped"
msg_info "Creating backup" DB_URL=$(sed -n 's/.*connection_string: "\(.*\)".*/\1/p' /opt/pangolin/config/config.yml)
tar -czf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin config create_backup /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 "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)" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_$(arch_resolve)"
@@ -55,23 +59,21 @@ function update_script() {
msg_info "Updating Pangolin" msg_info "Updating Pangolin"
cd /opt/pangolin cd /opt/pangolin
$STD npm ci $STD npm ci
$STD npm run set:sqlite $STD npm run set:pg
$STD npm run set:oss $STD npm run set:oss
rm -rf server/private rm -rf server/private
$STD npm run db:generate DATABASE_URL="$DB_URL" $STD npm run db:generate
$STD npm run build $STD npm run build
$STD npm run build:cli $STD npm run build:cli
cp -R .next/standalone ./ cp -R .next/standalone ./
cp -r server/migrations ./dist/init
chmod +x ./dist/cli.mjs chmod +x ./dist/cli.mjs
cp server/db/names.json ./dist/names.json cp server/db/names.json ./dist/names.json
cp server/db/ios_models.json ./dist/ios_models.json cp server/db/ios_models.json ./dist/ios_models.json
cp server/db/mac_models.json ./dist/mac_models.json cp server/db/mac_models.json ./dist/mac_models.json
msg_ok "Updated Pangolin" msg_ok "Updated Pangolin"
msg_info "Restoring config" restore_backup
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 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" msg_info "Adding migration step to pangolin.service"
@@ -82,13 +84,8 @@ function update_script() {
msg_info "Running database migrations" msg_info "Running database migrations"
cd /opt/pangolin 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 ENVIRONMENT=prod $STD node dist/migrations.mjs
msg_ok "Ran database migrations" msg_ok "Ran database migrations"
msg_info "Updating Badger plugin version" msg_info "Updating Badger plugin version"
@@ -112,4 +109,4 @@ description
msg_ok "Completed successfully!\n" msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW}Access it using the following URL:${CL}" echo -e "${INFO}${YW}Access it using the following URL:${CL}"
echo -e "${GATEWAY}${BGN}https://<YOUR_PANGOLIN_URL>${CL}" echo -e "${GATEWAY}${BGN}https://<YOUR_PANGOLIN_URL> or http://${IP}:3002${CL}"
+1 -1
View File
@@ -71,7 +71,7 @@ function update_script() {
cp /opt/pocket-id/.env /opt/env cp /opt/pocket-id/.env /opt/env
fi 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 mv /opt/env /opt/pocket-id/.env
msg_info "Starting Service" msg_info "Starting Service"
+77 -7
View File
@@ -106,13 +106,6 @@ spring.servlet.multipart.max-file-size=5GB
spring.servlet.multipart.max-request-size=5GB spring.servlet.multipart.max-request-size=5GB
server.tomcat.max-part-count=100 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 # Application-specific settings
reitti.server.advertise-uri= reitti.server.advertise-uri=
@@ -168,6 +161,81 @@ PROPEOF
msg_ok "Rewrote application.properties (backup: application.properties.bak)" msg_ok "Rewrote application.properties (backup: application.properties.bak)"
fi 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 if check_for_gh_release "reitti" "dedicatedcode/reitti"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop reitti systemctl stop reitti
@@ -179,10 +247,12 @@ PROPEOF
USE_ORIGINAL_FILENAME="true" fetch_and_deploy_gh_release "reitti" "dedicatedcode/reitti" "singlefile" "latest" "/opt/reitti" "reitti-app.jar" 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 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" msg_info "Starting Service"
systemctl start reitti systemctl start reitti
msg_ok "Started Service" msg_ok "Started Service"
msg_ok "Updated successfully!" 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 fi
exit exit
} }
+4 -6
View File
@@ -35,14 +35,12 @@ function update_script() {
systemctl stop snapotter systemctl stop snapotter
msg_ok "Stopped Service" msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "snapotter" "snapotter-hq/SnapOtter" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "snapotter" "snapotter-hq/SnapOtter" "prebuild" "latest" "/opt/snapotter" "snapotter-*-linux-amd64.tar.gz"
msg_info "Updating SnapOtter" msg_info "Updating SnapOtter"
cd /opt/snapotter $STD uv python install 3.11
$STD npm pkg delete scripts.prepare $STD uv venv --seed --python 3.11 /opt/snapotter_data/ai/venv
$STD pnpm install --frozen-lockfile ln -sfn /opt/snapotter /app
$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_ok "Updated SnapOtter"
msg_info "Starting Service" msg_info "Starting Service"
+2 -2
View File
@@ -32,7 +32,7 @@ function update_script() {
NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
if check_for_gl_release "storyteller" "storyteller-platform/storyteller"; then if check_for_gl_release "storyteller" "storyteller-platform/storyteller" "" "" "web-v2"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop storyteller systemctl stop storyteller
msg_ok "Stopped Service" msg_ok "Stopped Service"
@@ -41,7 +41,7 @@ function update_script() {
cp /opt/storyteller/.env /opt/storyteller_env.bak cp /opt/storyteller/.env /opt/storyteller_env.bak
msg_ok "Backed up Data" msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" CLEAN_INSTALL=1 fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" "" "web-v2"
msg_info "Restoring Configuration" msg_info "Restoring Configuration"
mv /opt/storyteller_env.bak /opt/storyteller/.env mv /opt/storyteller_env.bak /opt/storyteller/.env
+11 -2
View File
@@ -30,12 +30,14 @@ function update_script() {
exit exit
fi fi
if check_for_gh_release "wanderer" "Flomp/wanderer"; then if check_for_gh_release "wanderer" "open-wanderer/wanderer"; then
msg_info "Stopping service" msg_info "Stopping service"
systemctl stop wanderer-web systemctl stop wanderer-web
msg_ok "Stopped service" msg_ok "Stopped service"
fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source" 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
msg_info "Updating wanderer" msg_info "Updating wanderer"
cd /opt/wanderer/source/db cd /opt/wanderer/source/db
@@ -44,6 +46,13 @@ function update_script() {
cd /opt/wanderer/source/web cd /opt/wanderer/source/web
$STD npm ci $STD npm ci
$STD npm run build $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_ok "Updated wanderer"
msg_info "Starting service" msg_info "Starting service"
+64
View File
@@ -0,0 +1,64 @@
#!/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}"
+1
View File
@@ -72,6 +72,7 @@ BODY_SIZE_LIMIT=Infinity
ORIGIN='http://$LOCAL_IP:3000' ORIGIN='http://$LOCAL_IP:3000'
EOF EOF
cd /opt/adventurelog/frontend cd /opt/adventurelog/frontend
grep -q "^dangerouslyAllowAllBuilds:" ./pnpm-workspace.yaml 2>/dev/null || echo "dangerouslyAllowAllBuilds: true" >>./pnpm-workspace.yaml
$STD pnpm i $STD pnpm i
$STD pnpm build $STD pnpm build
msg_ok "Installed AdventureLog" msg_ok "Installed AdventureLog"
+215
View File
@@ -0,0 +1,215 @@
#!/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
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.26.3" "/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 <<EOF >/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)
$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 "initial"
mkdir -p /opt/affine/.turbo
cat <<TURBO >/opt/affine/.turbo/config.json
{
"concurrency": 1
}
TURBO
$STD corepack enable
$STD corepack prepare yarn@4.12.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 <<EOF >/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 <<EOF >/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 <<EOF >/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
+1 -1
View File
@@ -21,7 +21,7 @@ $STD apt install -y \
ffmpeg ffmpeg
msg_ok "Installed Dependencies" 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" msg_info "Setting up BirdNET-Go"
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
+8 -5
View File
@@ -26,8 +26,8 @@ msg_info "Installing ASP.NET Core Runtime"
if [[ "$(arch_resolve)" == "arm64" ]]; then if [[ "$(arch_resolve)" == "arm64" ]]; then
# packages.microsoft.com only ships amd64 debs for Debian; use dotnet-install on arm64 # 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 curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
$STD bash /tmp/dotnet-install.sh --channel 8.0 --runtime aspnetcore --install-dir /usr/lib/dotnet8 $STD bash /tmp/dotnet-install.sh --channel 10.0 --runtime aspnetcore --install-dir /usr/lib/dotnet10
ln -sf /usr/lib/dotnet8/dotnet /usr/bin/dotnet ln -sf /usr/lib/dotnet10/dotnet /usr/bin/dotnet
rm -f /tmp/dotnet-install.sh rm -f /tmp/dotnet-install.sh
else else
setup_deb822_repo \ setup_deb822_repo \
@@ -35,7 +35,7 @@ else
"https://packages.microsoft.com/keys/microsoft-2025.asc" \ "https://packages.microsoft.com/keys/microsoft-2025.asc" \
"https://packages.microsoft.com/debian/13/prod/" \ "https://packages.microsoft.com/debian/13/prod/" \
"trixie" "trixie"
$STD apt install -y aspnetcore-runtime-8.0 $STD apt install -y aspnetcore-runtime-10.0
fi fi
msg_ok "Installed ASP.NET Core Runtime" msg_ok "Installed ASP.NET Core Runtime"
@@ -55,9 +55,12 @@ if [[ "$install_server" =~ ^[Ss]$ ]]; then
msg_ok "Installed FileFlows Server" msg_ok "Installed FileFlows Server"
else else
msg_info "Installing FileFlows Node" 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 cd /opt/fileflows/Node
$STD dotnet FileFlows.Node.dll $STD dotnet FileFlows.Node.dll --server "$server_url" --systemd install --root true
$STD dotnet FileFlows.Node.dll --systemd install --root true
systemctl enable -q --now fileflows-node systemctl enable -q --now fileflows-node
msg_ok "Installed FileFlows Node" msg_ok "Installed FileFlows Node"
fi fi
+111
View File
@@ -0,0 +1,111 @@
#!/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 <<EOF >/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
+6
View File
@@ -24,6 +24,12 @@ msg_ok "Set up Hyperion repository"
msg_info "Installing Hyperion" msg_info "Installing Hyperion"
$STD apt install -y hyperion $STD apt install -y hyperion
mkdir -p /etc/systemd/system/hyperion@.service.d
cat <<EOF >/etc/systemd/system/hyperion@.service.d/override.conf
[Unit]
Requisite=
EOF
systemctl daemon-reload
systemctl enable -q --now hyperion@root systemctl enable -q --now hyperion@root
msg_ok "Installed Hyperion" msg_ok "Installed Hyperion"
+24 -2
View File
@@ -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=$(ls /etc/postgresql/ 2>/dev/null | sort -V | tail -1)
ACTUAL_PG_VERSION=${ACTUAL_PG_VERSION:-16} ACTUAL_PG_VERSION=${ACTUAL_PG_VERSION:-16}
VCHORD_RELEASE="1.0.0" VCHORD_RELEASE="1.1.1"
fetch_and_deploy_gh_release "VectorChord" "tensorchord/VectorChord" "binary" "${VCHORD_RELEASE}" "/tmp" "postgresql-${ACTUAL_PG_VERSION}-vchord_*_$(arch_resolve).deb" 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 sed -i "s/^#shared_preload.*/shared_preload_libraries = 'vchord.so'/" /etc/postgresql/${ACTUAL_PG_VERSION}/main/postgresql.conf
@@ -286,6 +286,7 @@ LIBVIPS_REVISION="e01a4797cabe77d457fdfa7d776b7a7e7ca6d6a7"
$STD git clone https://github.com/libvips/libvips.git "$SOURCE" $STD git clone https://github.com/libvips/libvips.git "$SOURCE"
cd "$SOURCE" cd "$SOURCE"
$STD git reset --hard "$LIBVIPS_REVISION" $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 $STD meson setup build --buildtype=release --libdir=lib -Dintrospection=disabled -Dtiff=disabled
cd build cd build
$STD ninja install $STD ninja install
@@ -311,7 +312,7 @@ ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata" GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache} mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.1" "$SRC_DIR" fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.2" "$SRC_DIR"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)" PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs
@@ -437,6 +438,27 @@ cd "$INSTALL_DIR"
ln -s "$GEO_DIR" "$APP_DIR" ln -s "$GEO_DIR" "$APP_DIR"
msg_ok "Installed GeoNames data" 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 mkdir -p /var/log/immich
touch /var/log/immich/{web.log,ml.log} touch /var/log/immich/{web.log,ml.log}
msg_ok "Installed Immich" msg_ok "Installed Immich"
+55
View File
@@ -0,0 +1,55 @@
#!/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 <<EOF >/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 <<EOF >/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
+75
View File
@@ -0,0 +1,75 @@
#!/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 <<EOF >/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
-85
View File
@@ -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 '-' </proc/sys/kernel/random/uuid)$(tr -d '-' </proc/sys/kernel/random/uuid)
ENCRYPTION_KEY=$(tr -d '-' </proc/sys/kernel/random/uuid)$(tr -d '-' </proc/sys/kernel/random/uuid)
mkdir -p /etc/nexterm-engine /etc/nexterm-server /opt/nexterm/data
cat <<EOF >/etc/nexterm-engine/config.yaml
server_host: "127.0.0.1"
server_port: 7800
registration_token: "${LOCAL_ENGINE_TOKEN}"
tls: false
EOF
cat <<EOF >/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 <<EOF >/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 <<EOF >/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
+1 -1
View File
@@ -64,7 +64,7 @@ $STD sudo -u cool coolconfig set-admin-password --user=admin --password="$COOLPA
echo "$COOLPASS" >~/.coolpass echo "$COOLPASS" >~/.coolpass
msg_ok "Installed Collabora Online" msg_ok "Installed Collabora Online"
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.2.1" "/usr/bin" "opencloud-*-linux-$(arch_resolve)" fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.2.2" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
mv /usr/bin/OpenCloud /usr/bin/opencloud mv /usr/bin/OpenCloud /usr/bin/opencloud
msg_info "Configuring OpenCloud" msg_info "Configuring OpenCloud"
+14 -7
View File
@@ -16,18 +16,19 @@ update_os
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt install -y \ $STD apt install -y \
build-essential \ build-essential \
python3 \
sqlite3 \
iptables iptables
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
NODE_VERSION="24" setup_nodejs NODE_VERSION="24" setup_nodejs
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.4}" PG_VERSION="17" setup_postgresql
PG_DB_NAME="pangolin" PG_DB_USER="pangolin" setup_postgresql_db
PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.20.0}"
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION" 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 "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" 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 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 read -rp "${TAB3}Enter your email address: " pango_email
msg_info "Setup Pangolin" msg_info "Setup Pangolin"
@@ -36,13 +37,14 @@ BADGER_VERSION=$(get_latest_github_release "fosrl/badger" "false")
cd /opt/pangolin cd /opt/pangolin
mkdir -p /opt/pangolin/config/{traefik,db,letsencrypt,logs} mkdir -p /opt/pangolin/config/{traefik,db,letsencrypt,logs}
$STD npm ci $STD npm ci
$STD npm run set:sqlite $STD npm run set:pg
$STD npm run set:oss $STD npm run set:oss
rm -rf server/private rm -rf server/private
$STD npm run db:generate DATABASE_URL="postgresql://pangolin:${PG_DB_PASS}@localhost:5432/pangolin" $STD npm run db:generate
$STD npm run build $STD npm run build
$STD npm run build:cli $STD npm run build:cli
cp -R .next/standalone ./ cp -R .next/standalone ./
cp -r server/migrations ./dist/init
cat <<EOF >/usr/local/bin/pangctl cat <<EOF >/usr/local/bin/pangctl
#!/bin/sh #!/bin/sh
@@ -74,6 +76,9 @@ flags:
require_email_verification: false require_email_verification: false
disable_signup_without_invite: false disable_signup_without_invite: false
disable_user_create_org: false disable_user_create_org: false
postgres:
connection_string: "postgresql://pangolin:${PG_DB_PASS}@localhost:5432/pangolin"
EOF EOF
cat <<EOF >/opt/pangolin/config/traefik/traefik_config.yml cat <<EOF >/opt/pangolin/config/traefik/traefik_config.yml
@@ -181,7 +186,8 @@ http:
servers: servers:
- url: "http://$LOCAL_IP:3000" - url: "http://$LOCAL_IP:3000"
EOF EOF
$STD npm run db:push export ENVIRONMENT=prod
$STD node dist/migrations.mjs
. /etc/os-release . /etc/os-release
if [ "$VERSION_CODENAME" = "trixie" ]; then if [ "$VERSION_CODENAME" = "trixie" ]; then
@@ -197,7 +203,8 @@ msg_info "Creating Services"
cat <<EOF >/etc/systemd/system/pangolin.service cat <<EOF >/etc/systemd/system/pangolin.service
[Unit] [Unit]
Description=Pangolin Service Description=Pangolin Service
After=network.target After=network.target postgresql.service
Wants=postgresql.service
[Service] [Service]
Type=simple Type=simple
+1 -1
View File
@@ -14,7 +14,7 @@ network_check
update_os update_os
read -r -p "${TAB3}What public URL do you want to use (e.g. pocketid.mydomain.com)? " public_url 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" msg_info "Configuring Pocket ID"
ENCRYPTION_KEY=$(openssl rand -base64 32) ENCRYPTION_KEY=$(openssl rand -base64 32)
+29 -15
View File
@@ -30,27 +30,30 @@ mv /opt/reitti/reitti-*.jar /opt/reitti/reitti.jar
msg_info "Installing Nginx Tile Cache" msg_info "Installing Nginx Tile Cache"
mkdir -p /var/cache/nginx/tiles mkdir -p /var/cache/nginx/tiles
cat <<EOF >/etc/nginx/nginx.conf cat <<'NGINXEOF' >/etc/nginx/nginx.conf
user www-data; user www-data;
events { events {
worker_connections 1024; worker_connections 1024;
} }
http { 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; proxy_cache_path /var/cache/nginx/tiles levels=1:2 keys_zone=tiles:10m max_size=1g inactive=30d use_temp_path=off;
server { server {
listen 80; listen 80;
location / { location /custom/ {
proxy_pass https://tile.openstreetmap.org/; set $upstream_url $http_x_reitti_upstream_url;
proxy_set_header Host tile.openstreetmap.org; proxy_pass $upstream_url;
proxy_set_header Host $proxy_host;
proxy_set_header User-Agent "Reitti/1.0"; proxy_set_header User-Agent "Reitti/1.0";
proxy_cache tiles; proxy_cache tiles;
proxy_cache_key $upstream_url;
proxy_cache_valid 200 30d; proxy_cache_valid 200 30d;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
} }
} }
} }
EOF NGINXEOF
chown -R www-data:www-data /var/cache/nginx chown -R www-data:www-data /var/cache/nginx
chmod -R 750 /var/cache/nginx chmod -R 750 /var/cache/nginx
systemctl restart nginx systemctl restart nginx
@@ -71,6 +74,7 @@ server.compression.mime-types=text/plain,application/json
logging.level.root=INFO logging.level.root=INFO
logging.level.org.hibernate.engine.jdbc.spi.SqlExceptionHelper=FATAL logging.level.org.hibernate.engine.jdbc.spi.SqlExceptionHelper=FATAL
logging.level.com.dedicatedcode.reitti=INFO logging.level.com.dedicatedcode.reitti=INFO
logging.level.org.quartz.core.ErrorLogger=FATAL
# Internationalization # Internationalization
spring.messages.basename=messages spring.messages.basename=messages
@@ -82,7 +86,7 @@ spring.messages.fallback-to-system-locale=false
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/$PG_DB_NAME spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/$PG_DB_NAME
spring.datasource.username=$PG_DB_USER spring.datasource.username=$PG_DB_USER
spring.datasource.password=$PG_DB_PASS spring.datasource.password=$PG_DB_PASS
spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.maximum-pool-size=30
# Redis configuration # Redis configuration
spring.data.redis.host=127.0.0.1 spring.data.redis.host=127.0.0.1
@@ -92,20 +96,23 @@ spring.data.redis.password=
spring.data.redis.database=0 spring.data.redis.database=0
spring.cache.redis.key-prefix= spring.cache.redis.key-prefix=
spring.cache.cache-names=processed-visits,significant-places,users,magic-links,configurations,transport-mode-configs,avatarThumbnails,avatarData,user-settings spring.cache.cache-names=processed-visits,significant-places,users,magic-links,configurations,transport-mode-configs,avatarThumbnails,avatarData,user-settings,devices,mapStyles,mapStyleJson
spring.cache.redis.time-to-live=1d spring.cache.redis.time-to-live=1d
# Upload configuration # Upload configuration
spring.servlet.multipart.max-file-size=5GB spring.servlet.multipart.max-file-size=5GB
spring.servlet.multipart.max-request-size=5GB spring.servlet.multipart.max-request-size=5GB
spring.servlet.multipart.resolve-lazily=true
server.tomcat.max-part-count=100 server.tomcat.max-part-count=100
spring.mvc.async.request-timeout=600000
# Rqueue configuration # Quartz Scheduler configuration
rqueue.web.enable=false spring.quartz.job-store-type=jdbc
rqueue.job.enabled=false spring.quartz.jdbc.initialize-schema=never
rqueue.message.durability.in-terminal-state=0 spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
rqueue.key.prefix=\${spring.cache.redis.key-prefix} spring.quartz.properties.org.quartz.jobStore.isClustered=false
rqueue.message.converter.provider.class=com.dedicatedcode.reitti.config.RQueueCustomMessageConverter spring.quartz.properties.org.quartz.jobStore.tablePrefix=qrtz_
spring.quartz.properties.org.quartz.threadPool.threadCount=5
# Application-specific settings # Application-specific settings
reitti.server.advertise-uri= reitti.server.advertise-uri=
@@ -117,18 +124,25 @@ reitti.security.oidc.enabled=false
reitti.security.oidc.registration.enabled=false reitti.security.oidc.registration.enabled=false
reitti.import.batch-size=10000 reitti.import.batch-size=10000
reitti.import.processing-idle-start-time=10 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.geo-point-filter.max-speed-kmh=1000 reitti.geo-point-filter.max-speed-kmh=1000
reitti.geo-point-filter.max-accuracy-meters=100 reitti.geo-point-filter.max-accuracy-meters=100
reitti.geo-point-filter.history-lookback-hours=24 reitti.geo-point-filter.history-lookback-hours=24
reitti.geo-point-filter.window-size=50 reitti.geo-point-filter.window-size=50
reitti.process-data.schedule=0 */10 * * * *
reitti.process-data.refresh-views.schedule=0 0 4 * * * reitti.process-data.refresh-views.schedule=0 0 4 * * *
reitti.imports.schedule=0 5/10 * * * * reitti.imports.schedule=0 5/10 * * * *
reitti.imports.owntracks-recorder.schedule=\${reitti.imports.schedule} 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 # Geocoding service configuration
reitti.geocoding.max-errors=10 reitti.geocoding.max-errors=10
reitti.geocoding.photon.base-url= reitti.geocoding.photon.base-url=
+1 -1
View File
@@ -54,7 +54,7 @@ cronKey=$(head -c 1024 </dev/urandom | sha256sum | awk '{print substr($1,1,29)}'
sed -i -e 's/Shinobi/'"$cronKey"'/g' conf.json sed -i -e 's/Shinobi/'"$cronKey"'/g' conf.json
cp super.sample.json super.json cp super.sample.json super.json
$STD npm i npm -g $STD npm i npm -g
$STD npm install --unsafe-perm $STD npm install
$STD npm install pm2@latest -g $STD npm install pm2@latest -g
chmod -R 755 . chmod -R 755 .
touch INSTALL/installed.txt touch INSTALL/installed.txt
+12
View File
@@ -16,6 +16,17 @@ update_os
fetch_and_deploy_gh_release "silverbullet" "silverbulletmd/silverbullet" "prebuild" "latest" "/opt/silverbullet/bin" "silverbullet-server-linux-$(arch_resolve "x86_64" "aarch64").zip" fetch_and_deploy_gh_release "silverbullet" "silverbulletmd/silverbullet" "prebuild" "latest" "/opt/silverbullet/bin" "silverbullet-server-linux-$(arch_resolve "x86_64" "aarch64").zip"
mkdir -p /opt/silverbullet/space mkdir -p /opt/silverbullet/space
RUNTIME_API_ENV=""
read -rp "${TAB3}Enable Silverbullet Runtime API? Requires Chromium (~700MB). Uses ~200MB extra RAM. (y/N): " runtime_api_prompt
if [[ "${runtime_api_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Chromium for Runtime API"
$STD apt install -y chromium
msg_ok "Installed Chromium for Runtime API"
RUNTIME_API_ENV=$'Environment=SB_CHROME_PATH=/usr/bin/chromium\nEnvironment=SB_CHROME_DATA_DIR=/opt/silverbullet/space/.chrome-data\n'
touch /opt/silverbullet/.runtime-api-enabled
msg_ok "Runtime API will be enabled"
fi
msg_info "Creating Service" msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/silverbullet.service cat <<EOF >/etc/systemd/system/silverbullet.service
[Unit] [Unit]
@@ -25,6 +36,7 @@ After=syslog.target network.target
[Service] [Service]
User=root User=root
Type=simple Type=simple
${RUNTIME_API_ENV}
ExecStart=/opt/silverbullet/bin/silverbullet --hostname 0.0.0.0 --port 3000 /opt/silverbullet/space ExecStart=/opt/silverbullet/bin/silverbullet --hostname 0.0.0.0 --port 3000 /opt/silverbullet/space
WorkingDirectory=/opt/silverbullet WorkingDirectory=/opt/silverbullet
Restart=on-failure Restart=on-failure
+1 -1
View File
@@ -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" 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 ln -sf /opt/readium/readium /usr/local/bin/readium
fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" fetch_and_deploy_gl_release "storyteller" "storyteller-platform/storyteller" "tarball" "latest" "/opt/storyteller" "" "web-v2"
msg_info "Setting up Storyteller" msg_info "Setting up Storyteller"
cd /opt/storyteller cd /opt/storyteller
+8 -1
View File
@@ -20,7 +20,8 @@ if [[ "$(arch_resolve)" == "arm64" ]]; then
else else
fetch_and_deploy_gh_release "meilisearch" "meilisearch/meilisearch" "binary" "latest" "/opt/wanderer/source/search" fetch_and_deploy_gh_release "meilisearch" "meilisearch/meilisearch" "binary" "latest" "/opt/wanderer/source/search"
fi fi
mkdir -p /opt/wanderer/{source,data/pb_data,data/meili_data} mkdir -p /opt/wanderer/{source,data/pb_data,data/meili_data,data/plugins}
[[ -e /data/plugins ]] || ln -sfn /opt/wanderer/data/plugins /data/plugins
fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source" fetch_and_deploy_gh_release "wanderer" "open-wanderer/wanderer" "tarball" "latest" "/opt/wanderer/source"
msg_info "Installing wanderer (patience)" msg_info "Installing wanderer (patience)"
@@ -32,6 +33,12 @@ $STD npm ci
$STD npm run build $STD npm run build
msg_ok "Installed wanderer" 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" msg_info "Creating Service"
MEILI_KEY=$(openssl rand -hex 32) MEILI_KEY=$(openssl rand -hex 32)
POCKETBASE_KEY=$(openssl rand -hex 16) POCKETBASE_KEY=$(openssl rand -hex 16)
+72
View File
@@ -0,0 +1,72 @@
#!/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 <<EOF >/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 <<EOF >/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
+9 -10
View File
@@ -3764,19 +3764,18 @@ runtime_script_status_guard() {
return 0 return 0
fi fi
if ! command -v jq >/dev/null 2>&1; then local is_deleted is_disabled deleted_message disable_message info_url
msg_warn "Missing jq for script status check. Continuing without status verification." if printf '%s' "$response" | grep -qE '"items":[[:space:]]*\[[[:space:]]*\]'; then
return 0 return 0
fi fi
local has_record is_deleted is_disabled deleted_message disable_message info_url # PocketBase returns a flat, fixed-field JSON blob; sed is enough here (no jq needed).
has_record=$(printf '%s' "$response" | jq -r '.items | length') is_deleted=$(printf '%s' "$response" | sed -n 's/.*"is_deleted"[[:space:]]*:[[:space:]]*\(true\|false\).*/\1/p' | head -1)
[[ "$has_record" == "0" ]] && return 0 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)
is_deleted=$(printf '%s' "$response" | jq -r '.items[0].is_deleted // false') disable_message=$(printf '%s' "$response" | sed -n 's/.*"disable_message"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1)
is_disabled=$(printf '%s' "$response" | jq -r '.items[0].is_disabled // false') is_deleted=${is_deleted:-false}
deleted_message=$(printf '%s' "$response" | jq -r '.items[0].deleted_message // ""') is_disabled=${is_disabled:-false}
disable_message=$(printf '%s' "$response" | jq -r '.items[0].disable_message // ""')
info_url="https://community-scripts.org/scripts/${script_slug}" info_url="https://community-scripts.org/scripts/${script_slug}"
if [[ "$is_deleted" == "true" ]]; then if [[ "$is_deleted" == "true" ]]; then
+283 -28
View File
@@ -36,6 +36,10 @@
# #
# ============================================================================== # ==============================================================================
# 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 # Debug helper - outputs to stderr when TOOLS_DEBUG is enabled
# Usage: debug_log "message" # Usage: debug_log "message"
@@ -91,16 +95,17 @@ curl_with_retry() {
while [[ $attempt -le $retries ]]; do while [[ $attempt -le $retries ]]; do
debug_log "curl attempt $attempt/$retries: $url" debug_log "curl attempt $attempt/$retries: $url"
local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout" # Build curl command as array to avoid command injection via extra_opts
[[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $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[@]}")
if [[ "$output" == "-" ]]; then if [[ "$output" == "-" ]]; then
if $curl_cmd "$url"; then if "${curl_args[@]}" "$url"; then
success=true success=true
break break
fi fi
else else
if $curl_cmd -o "$output" "$url"; then if "${curl_args[@]}" -o "$output" "$url"; then
success=true success=true
break break
fi fi
@@ -153,15 +158,16 @@ curl_api_with_retry() {
while [[ $attempt -le $retries ]]; do while [[ $attempt -le $retries ]]; do
debug_log "curl API attempt $attempt/$retries: $url" debug_log "curl API attempt $attempt/$retries: $url"
local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout -w '%{http_code}'" # Build curl command as array to avoid command injection via extra_opts
[[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $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[@]}")
if [[ -n "$body_file" ]]; then if [[ -n "$body_file" ]]; then
http_code=$($curl_cmd -o "$body_file" "$url" 2>/dev/null) || true http_code=$("${curl_args[@]}" -o "$body_file" "$url" 2>/dev/null) || true
else else
# Capture body and http_code separately # Capture body and http_code separately
local tmp_body="/tmp/curl_api_body_$$" local tmp_body="/tmp/curl_api_body_$$"
http_code=$($curl_cmd -o "$tmp_body" "$url" 2>/dev/null) || true http_code=$("${curl_args[@]}" -o "$tmp_body" "$url" 2>/dev/null) || true
if [[ -f "$tmp_body" ]]; then if [[ -f "$tmp_body" ]]; then
cat "$tmp_body" cat "$tmp_body"
rm -f "$tmp_body" rm -f "$tmp_body"
@@ -304,7 +310,10 @@ edit_yaml_config() {
return 1 return 1
fi fi
sed -i "s|^\([[:space:]]*${key}[[:space:]]*:\).*|\1 ${value}|" "$file" # 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"
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -1687,10 +1696,6 @@ is_ubuntu() {
[[ "$(get_os_info id)" == "ubuntu" ]] [[ "$(get_os_info id)" == "ubuntu" ]]
} }
is_alpine() {
[[ "$(get_os_info id)" == "alpine" ]]
}
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Get Debian/Ubuntu major version # Get Debian/Ubuntu major version
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -2454,8 +2459,10 @@ start_timer() {
end_timer() { end_timer() {
local start_time="$1" local start_time="$1"
local label="${2:-Operation}" local label="${2:-Operation}"
local end_time=$(date +%s) local end_time
end_time=$(date +%s)
local duration=$((end_time - start_time)) local duration=$((end_time - start_time))
echo "${label} took ${duration}s"
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -2559,6 +2566,199 @@ fetch_and_deploy_gh_tag() {
return 0 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 ~/.<app> 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 ~/.<app> 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
local filename="${app_lc}-${version_safe}.tar.gz"
msg_info "Fetching GitLab tag: ${app} (${resolved_tag})"
curl $download_timeout -fsSL "${header[@]}" -o "$tmpdir/$filename" "$tarball_url" || {
msg_error "Download failed: $tarball_url"
rm -rf "$tmpdir"
return 7
}
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 "$resolved_tag" >"$version_file"
msg_ok "Deployed ${app} ${resolved_tag} to ${target}"
return 0
}
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Checks for new GitHub tag (for repos without releases). # Checks for new GitHub tag (for repos without releases).
# #
@@ -2633,6 +2833,7 @@ check_for_gh_release() {
local source="$2" local source="$2"
local pinned_version_in="${3:-}" # optional local pinned_version_in="${3:-}" # optional
local pin_reason="${4:-}" # optional reason shown to user local pin_reason="${4:-}" # optional reason shown to user
local tag_prefix="${5:-}" # optional tag prefix filter (e.g. web-v2)
local app_lc="" local app_lc=""
app_lc="$(echo "${app,,}" | tr -d ' ')" app_lc="$(echo "${app,,}" | tr -d ' ')"
local current_file="$HOME/.${app_lc}" local current_file="$HOME/.${app_lc}"
@@ -2688,7 +2889,7 @@ check_for_gh_release() {
rm -f "$gh_check_json" rm -f "$gh_check_json"
fi fi
if [[ -z "$pinned_version_in" ]]; then if [[ -z "$pinned_version_in" && -z "$tag_prefix" ]]; then
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \ http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \
-H 'Accept: application/vnd.github+json' \ -H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \ -H 'X-GitHub-Api-Version: 2022-11-28' \
@@ -2716,7 +2917,7 @@ check_for_gh_release() {
rm -f "$gh_check_json" rm -f "$gh_check_json"
fi fi
# If no releases yet (pinned version OR /latest failed), fetch up to 100 # If no releases yet (pinned version, tag prefix, OR /latest failed), fetch up to 100
if [[ -z "$releases_json" ]]; then if [[ -z "$releases_json" ]]; then
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \ http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gh_check_json" \
-H 'Accept: application/vnd.github+json' \ -H 'Accept: application/vnd.github+json' \
@@ -2754,9 +2955,18 @@ check_for_gh_release() {
rm -f "$gh_check_json" rm -f "$gh_check_json"
fi fi
mapfile -t raw_tags < <(jq -r '.[] | select(.draft==false and .prerelease==false) | .tag_name' <<<"$releases_json") 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
if ((${#raw_tags[@]} == 0)); then if ((${#raw_tags[@]} == 0)); then
msg_error "No stable releases found for ${app}" 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
return 250 return 250
fi fi
@@ -3760,6 +3970,7 @@ fetch_and_deploy_gh_release() {
local version="${var_appversion:-${4:-latest}}" local version="${var_appversion:-${4:-latest}}"
local target="${5:-/opt/$app}" local target="${5:-/opt/$app}"
local asset_pattern="${6:-}" local asset_pattern="${6:-}"
local tag_prefix="${7:-}"
# Validate app name to prevent /root/. directory issues # Validate app name to prevent /root/. directory issues
if [[ -z "$app" ]]; then if [[ -z "$app" ]]; then
@@ -3789,7 +4000,13 @@ fetch_and_deploy_gh_release() {
TOOLS_GH_REL_JSON="$gh_rel_json" TOOLS_GH_REL_JSON="$gh_rel_json"
local api_url="https://api.github.com/repos/$repo/releases" local api_url="https://api.github.com/repos/$repo/releases"
[[ "$version" != "latest" ]] && api_url="$api_url/tags/$version" || api_url="$api_url/latest" 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
local header=() local header=()
[[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN") [[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN")
@@ -3852,6 +4069,14 @@ fetch_and_deploy_gh_release() {
local json tag_name local json tag_name
json=$(<"$gh_rel_json") 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') 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/..." # 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" [[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
@@ -6746,9 +6971,11 @@ setup_mariadb_db() {
msg_info "Setting up MariaDB Database" msg_info "Setting up MariaDB Database"
$STD mariadb -u root -e "CREATE DATABASE \`$MARIADB_DB_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # Use --defaults-extra-file to pass credentials safely and escape identifiers
$STD mariadb -u root -e "CREATE USER '$MARIADB_DB_USER'@'localhost' IDENTIFIED BY '$MARIADB_DB_PASS';" # to prevent SQL injection via DB name / user / password
$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 # Optional extra grants
if [[ -n "${MARIADB_DB_EXTRA_GRANTS:-}" ]]; then if [[ -n "${MARIADB_DB_EXTRA_GRANTS:-}" ]]; then
@@ -8378,8 +8605,14 @@ setup_postgresql_db() {
fi fi
msg_info "Setting up PostgreSQL Database" msg_info "Setting up PostgreSQL Database"
$STD sudo -u postgres psql -c "CREATE ROLE $PG_DB_USER WITH LOGIN PASSWORD '$PG_DB_PASS';" # Escape single quotes in identifiers to prevent SQL injection
$STD sudo -u postgres psql -c "CREATE DATABASE $PG_DB_NAME WITH OWNER $PG_DB_USER ENCODING 'UTF8' TEMPLATE template0;" 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;"
# Configure pg_cron database BEFORE creating the extension (must be set before pg_cron loads) # 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 if [[ -n "${PG_DB_EXTENSIONS:-}" ]] && [[ ",${PG_DB_EXTENSIONS//[[:space:]]/}," == *",pg_cron,"* ]]; then
@@ -9276,6 +9509,7 @@ check_for_gl_release() {
local source="$2" local source="$2"
local pinned_version_in="${3:-}" # optional local pinned_version_in="${3:-}" # optional
local pin_reason="${4:-}" # optional reason shown to user 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 app_lc="${app,,}"
local current_file="$HOME/.${app_lc}" local current_file="$HOME/.${app_lc}"
@@ -9352,9 +9586,18 @@ check_for_gl_release() {
rm -f "$gl_check_json" rm -f "$gl_check_json"
fi fi
mapfile -t raw_tags < <(jq -r '.[] | .tag_name' <<<"$releases_json") 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
if ((${#raw_tags[@]} == 0)); then if ((${#raw_tags[@]} == 0)); then
msg_error "No releases found for ${app} on GitLab" 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
return 250 return 250
fi fi
@@ -9549,6 +9792,7 @@ fetch_and_deploy_gl_release() {
local version="${var_appversion:-${4:-latest}}" local version="${var_appversion:-${4:-latest}}"
local target="${5:-/opt/$app}" local target="${5:-/opt/$app}"
local asset_pattern="${6:-}" local asset_pattern="${6:-}"
local tag_prefix="${7:-}"
if [[ -z "$app" ]]; then if [[ -z "$app" ]]; then
app="${repo##*/}" app="${repo##*/}"
@@ -9580,6 +9824,8 @@ fetch_and_deploy_gl_release() {
local api_url local api_url
if [[ "$version" != "latest" ]]; then if [[ "$version" != "latest" ]]; then
api_url="$api_base/$version" api_url="$api_base/$version"
elif [[ -n "$tag_prefix" ]]; then
api_url="$api_base?per_page=100&order_by=released_at&sort=desc"
else else
api_url="$api_base?per_page=1&order_by=released_at&sort=desc" api_url="$api_base?per_page=1&order_by=released_at&sort=desc"
fi fi
@@ -9634,9 +9880,18 @@ fetch_and_deploy_gl_release() {
json=$(<"$gl_rel_json") json=$(<"$gl_rel_json")
if [[ "$version" == "latest" ]]; then if [[ "$version" == "latest" ]]; then
json=$(echo "$json" | jq '.[0] // empty') 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
if [[ -z "$json" || "$json" == "null" ]]; then if [[ -z "$json" || "$json" == "null" ]]; then
msg_error "No releases found for $repo on GitLab" 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
return 1 return 1
fi fi
fi fi
+1 -1
View File
@@ -475,7 +475,7 @@ function advanced_settings() {
done done
while true; do 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 if [ -z "$VLAN1" ]; then
VLAN1="Default" VLAN1="Default"
VLAN="" VLAN=""