mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-06-02 21:59:35 +02:00
Compare commits
124 Commits
fix/docuse
...
pocketbase
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f42110d827 | ||
|
|
cdc428dd60 | ||
|
|
354ceef128 | ||
|
|
1a6dbb0bf8 | ||
|
|
f14eca3bc9 | ||
|
|
d4b4880e0d | ||
|
|
9dc08aa8c1 | ||
|
|
06af8cca46 | ||
|
|
5668ad9a8d | ||
|
|
bd9bae075d | ||
|
|
7cdb6c8133 | ||
|
|
6315547e65 | ||
|
|
e9a9bf17ee | ||
|
|
40b86bef63 | ||
|
|
a43ca27d2f | ||
|
|
ee06ac1819 | ||
|
|
1a63343a17 | ||
|
|
cd8a6f1de0 | ||
|
|
da64475612 | ||
|
|
a2aea34aa7 | ||
|
|
839fba1e0c | ||
|
|
83398645ca | ||
|
|
06cf2ec50d | ||
|
|
bdc968e86d | ||
|
|
0b7d64b240 | ||
|
|
e013403db1 | ||
|
|
465996653a | ||
|
|
6a7391f430 | ||
|
|
aed34659c9 | ||
|
|
cd4a3e854e | ||
|
|
be46da731a | ||
|
|
58179050a8 | ||
|
|
955cb97a3b | ||
|
|
04e618798e | ||
|
|
4c358450d8 | ||
|
|
fa238ddbdd | ||
|
|
0fe653f8de | ||
|
|
278e8315f3 | ||
|
|
ded4bba04d | ||
|
|
5b6f8e2674 | ||
|
|
162cb9b887 | ||
|
|
5776f3fef5 | ||
|
|
26377b7a7f | ||
|
|
151cd6581f | ||
|
|
69641d322d | ||
|
|
6608deeb92 | ||
|
|
de7c00e285 | ||
|
|
eb74ba2edb | ||
|
|
203131d042 | ||
|
|
44db73c58d | ||
|
|
d074d3f292 | ||
|
|
65f3a23cff | ||
|
|
4da4a47eb7 | ||
|
|
cf3d8f902c | ||
|
|
8c0333151b | ||
|
|
dc355d07bf | ||
|
|
4e51373669 | ||
|
|
256020b847 | ||
|
|
19cd2b3dad | ||
|
|
9c06910526 | ||
|
|
d3feeb4900 | ||
|
|
4926d426a8 | ||
|
|
7fea6cc9eb | ||
|
|
b59ab46000 | ||
|
|
d41fd37f1a | ||
|
|
b065c5e081 | ||
|
|
1f9c670648 | ||
|
|
fdfb603930 | ||
|
|
9a05da0b60 | ||
|
|
38a14454c4 | ||
|
|
c3294436b5 | ||
|
|
44a4c97a4c | ||
|
|
8c9477506c | ||
|
|
f7224f3db8 | ||
|
|
03dd5e7e88 | ||
|
|
7b5e2f9656 | ||
|
|
7703edf4b6 | ||
|
|
32f1956023 | ||
|
|
49817d14f8 | ||
|
|
d64b9f6878 | ||
|
|
1fde72e141 | ||
|
|
ceb50e3528 | ||
|
|
287c60bc08 | ||
|
|
9764462f06 | ||
|
|
dc7ea8f526 | ||
|
|
0c8c11f6b4 | ||
|
|
b2bcffbb05 | ||
|
|
6a91a57cb2 | ||
|
|
7e5f7a329e | ||
|
|
80a73c0ec0 | ||
|
|
d9f88aba7f | ||
|
|
8ed57f08bf | ||
|
|
c6dcd986ce | ||
|
|
a36b2c9be7 | ||
|
|
e04a9dc13e | ||
|
|
c6f2c2b7d0 | ||
|
|
f78c2be766 | ||
|
|
edfa7c8c45 | ||
|
|
f378e76329 | ||
|
|
faf073d3b5 | ||
|
|
43fc5c27e1 | ||
|
|
37649c1e0a | ||
|
|
bb5f531761 | ||
|
|
48b34d4c2e | ||
|
|
54e13bca94 | ||
|
|
9aa76e8ea4 | ||
|
|
219c4e80b0 | ||
|
|
35cd953ed7 | ||
|
|
f9f21c1b79 | ||
|
|
62a6122fa6 | ||
|
|
45953e857a | ||
|
|
d984a5828d | ||
|
|
8492ca5805 | ||
|
|
9ec0864d32 | ||
|
|
6a9081726f | ||
|
|
514fece0df | ||
|
|
9c1f80e3c9 | ||
|
|
4dc5dfb366 | ||
|
|
4b2cacf78f | ||
|
|
e5c66aa4d2 | ||
|
|
b00ae8c350 | ||
|
|
7cfa47d138 | ||
|
|
639dc9efc4 | ||
|
|
5bf9cfb800 |
264
.github/changelogs/2026/05.md
generated
vendored
264
.github/changelogs/2026/05.md
generated
vendored
@@ -1,3 +1,267 @@
|
|||||||
|
## 2026-05-30
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Flatnotes: fix empty package name in pyproject.toml [@MickLesk](https://github.com/MickLesk) ([#14814](https://github.com/community-scripts/ProxmoxVE/pull/14814))
|
||||||
|
|
||||||
|
## 2026-05-29
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- Kan ([#14776](https://github.com/community-scripts/ProxmoxVE/pull/14776))
|
||||||
|
- Dynacat ([#14777](https://github.com/community-scripts/ProxmoxVE/pull/14777))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fix lobehub docker path [@dannyyy](https://github.com/dannyyy) ([#14793](https://github.com/community-scripts/ProxmoxVE/pull/14793))
|
||||||
|
- karakeep: add more hdd space [@MickLesk](https://github.com/MickLesk) ([#14797](https://github.com/community-scripts/ProxmoxVE/pull/14797))
|
||||||
|
- Grist: Revert installation of EE [@tremor021](https://github.com/tremor021) ([#14784](https://github.com/community-scripts/ProxmoxVE/pull/14784))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Sure: Remove `$STD` for `systemctl enable -q` [@tremor021](https://github.com/tremor021) ([#14801](https://github.com/community-scripts/ProxmoxVE/pull/14801))
|
||||||
|
|
||||||
|
## 2026-05-28
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- RomM: remove nginx default.conf during installation [@MickLesk](https://github.com/MickLesk) ([#14766](https://github.com/community-scripts/ProxmoxVE/pull/14766))
|
||||||
|
- Open-Archiver: replace pnpm approve-builds --yes with --all [@MickLesk](https://github.com/MickLesk) ([#14765](https://github.com/community-scripts/ProxmoxVE/pull/14765))
|
||||||
|
- fix(hermesagent): set npm_config_yes=true to suppress interactive pro… [@steveonjava](https://github.com/steveonjava) ([#14763](https://github.com/community-scripts/ProxmoxVE/pull/14763))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Yamtrack: migrate to uv [@MickLesk](https://github.com/MickLesk) ([#14767](https://github.com/community-scripts/ProxmoxVE/pull/14767))
|
||||||
|
|
||||||
|
### ❔ Uncategorized
|
||||||
|
|
||||||
|
- chore(ct): sync adventurelog defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#14772](https://github.com/community-scripts/ProxmoxVE/pull/14772))
|
||||||
|
|
||||||
|
## 2026-05-27
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- MusicSeerr ([#14746](https://github.com/community-scripts/ProxmoxVE/pull/14746))
|
||||||
|
- Hermes Agent ([#14751](https://github.com/community-scripts/ProxmoxVE/pull/14751))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- grist: restore install:ee step [@paulfitz](https://github.com/paulfitz) ([#14759](https://github.com/community-scripts/ProxmoxVE/pull/14759))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- [tools.func]: `setup_gs()` fix getting dotted release format [@tremor021](https://github.com/tremor021) ([#14745](https://github.com/community-scripts/ProxmoxVE/pull/14745))
|
||||||
|
|
||||||
|
## 2026-05-26
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Add directory creation to Profilarr update script [@ryansully](https://github.com/ryansully) ([#14740](https://github.com/community-scripts/ProxmoxVE/pull/14740))
|
||||||
|
- profilarr: Fix ARCH assignment in profilarr.sh to support Profilarr build usage [@mpeleshenko](https://github.com/mpeleshenko) ([#14709](https://github.com/community-scripts/ProxmoxVE/pull/14709))
|
||||||
|
- Jackett: Remove quotes in Service File [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14729](https://github.com/community-scripts/ProxmoxVE/pull/14729))
|
||||||
|
- Open-archiver: approve pnpm build scripts and run build:oss without subshell [@MickLesk](https://github.com/MickLesk) ([#14711](https://github.com/community-scripts/ProxmoxVE/pull/14711))
|
||||||
|
- Docuseal: read Ruby version from Gemfile, upgrade on update if needed [@MickLesk](https://github.com/MickLesk) ([#14715](https://github.com/community-scripts/ProxmoxVE/pull/14715))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Birdnet-GO: install libonnxruntime.so from release tarball [@MickLesk](https://github.com/MickLesk) ([#14716](https://github.com/community-scripts/ProxmoxVE/pull/14716))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: better error diagnostics, consistent OS detection, setup function ordering [@MickLesk](https://github.com/MickLesk) ([#14692](https://github.com/community-scripts/ProxmoxVE/pull/14692))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- IPTag-Tool: use qm set for VM tags to handle snapshot sections crrectly [@MickLesk](https://github.com/MickLesk) ([#14713](https://github.com/community-scripts/ProxmoxVE/pull/14713))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Netdata: extend PVE version support to 9.x [@MickLesk](https://github.com/MickLesk) ([#14714](https://github.com/community-scripts/ProxmoxVE/pull/14714))
|
||||||
|
|
||||||
|
## 2026-05-25
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- karakeep: fix: pip config [@CrazyWolf13](https://github.com/CrazyWolf13) ([#14703](https://github.com/community-scripts/ProxmoxVE/pull/14703))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: replace raw GitHub API curl calls with get_latest_github_release [@MickLesk](https://github.com/MickLesk) ([#14690](https://github.com/community-scripts/ProxmoxVE/pull/14690))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Kernel-Clean: detect meta-packages and fix silent removal failures [@MickLesk](https://github.com/MickLesk) ([#14674](https://github.com/community-scripts/ProxmoxVE/pull/14674))
|
||||||
|
|
||||||
|
## 2026-05-24
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- RomM: add installation steps for Nginx mod_zip module [@MickLesk](https://github.com/MickLesk) ([#14678](https://github.com/community-scripts/ProxmoxVE/pull/14678))
|
||||||
|
- ISponsorblockTV: detect CPU capabilities to select compatible binary [@MickLesk](https://github.com/MickLesk) ([#14677](https://github.com/community-scripts/ProxmoxVE/pull/14677))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Refactor: MQTT [@tremor021](https://github.com/tremor021) ([#14673](https://github.com/community-scripts/ProxmoxVE/pull/14673))
|
||||||
|
|
||||||
|
## 2026-05-23
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- IronClaw: Extra configuration during install to ensure Web Gateway can run [@SystemIdleProcess](https://github.com/SystemIdleProcess) ([#14635](https://github.com/community-scripts/ProxmoxVE/pull/14635))
|
||||||
|
- Tunarr: fix path to backup during update [@SystemIdleProcess](https://github.com/SystemIdleProcess) ([#14655](https://github.com/community-scripts/ProxmoxVE/pull/14655))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- wealthfolio: add: prebuild [@CrazyWolf13](https://github.com/CrazyWolf13) ([#14658](https://github.com/community-scripts/ProxmoxVE/pull/14658))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- kernel-clean: support range syntax in selection prompt [@djhojd](https://github.com/djhojd) ([#14656](https://github.com/community-scripts/ProxmoxVE/pull/14656))
|
||||||
|
|
||||||
|
## 2026-05-22
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- bitfocus-companion ([#14603](https://github.com/community-scripts/ProxmoxVE/pull/14603))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- fix(the-lounge): install Node.js 22 before deb package [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14648](https://github.com/community-scripts/ProxmoxVE/pull/14648))
|
||||||
|
- Docmost: Fix duplicate STORAGE_DRIVER [@MickLesk](https://github.com/MickLesk) ([#14645](https://github.com/community-scripts/ProxmoxVE/pull/14645))
|
||||||
|
- Profilarr: pin Deno version to v2.7.5 [@MickLesk](https://github.com/MickLesk) ([#14632](https://github.com/community-scripts/ProxmoxVE/pull/14632))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- add: karakeep cli wrapper [@CrazyWolf13](https://github.com/CrazyWolf13) ([#14618](https://github.com/community-scripts/ProxmoxVE/pull/14618))
|
||||||
|
|
||||||
|
- #### 💥 Breaking Changes
|
||||||
|
|
||||||
|
- OpenCloud: v7.0.0 changes [@vhsdream](https://github.com/vhsdream) ([#14650](https://github.com/community-scripts/ProxmoxVE/pull/14650))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- workflows: update workflows, templates to support arm64. [@asylumexp](https://github.com/asylumexp) ([#14653](https://github.com/community-scripts/ProxmoxVE/pull/14653))
|
||||||
|
- SoulSync: setup Node v22 and build WebUI [@MickLesk](https://github.com/MickLesk) ([#14639](https://github.com/community-scripts/ProxmoxVE/pull/14639))
|
||||||
|
- Refactor: Dispatcharr [@MickLesk](https://github.com/MickLesk) ([#14313](https://github.com/community-scripts/ProxmoxVE/pull/14313))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- fix: make LXC banner OS detection dynamic via /etc/os-release [@atahan99](https://github.com/atahan99) ([#14269](https://github.com/community-scripts/ProxmoxVE/pull/14269))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- core: suppress MOTD for non-interactive shells [@MickLesk](https://github.com/MickLesk) ([#14638](https://github.com/community-scripts/ProxmoxVE/pull/14638))
|
||||||
|
|
||||||
|
## 2026-05-21
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- snowshare: use mv instead of cp for uploads backup to prevent disk fill [@TuroYT](https://github.com/TuroYT) ([#14558](https://github.com/community-scripts/ProxmoxVE/pull/14558))
|
||||||
|
- Technitium DNS: download release before stopping the service on update [@w-gitops](https://github.com/w-gitops) ([#14616](https://github.com/community-scripts/ProxmoxVE/pull/14616))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Proxmox VE 9.2 support [@MickLesk](https://github.com/MickLesk) ([#14624](https://github.com/community-scripts/ProxmoxVE/pull/14624))
|
||||||
|
|
||||||
|
## 2026-05-20
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Update mylar3 to point to new Repo [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14606](https://github.com/community-scripts/ProxmoxVE/pull/14606))
|
||||||
|
- Ollama: Fix for latest version [@tremor021](https://github.com/tremor021) ([#14596](https://github.com/community-scripts/ProxmoxVE/pull/14596))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Profilarr v2: Update and Refactor whole Script [@MickLesk](https://github.com/MickLesk) ([#14584](https://github.com/community-scripts/ProxmoxVE/pull/14584))
|
||||||
|
|
||||||
|
## 2026-05-19
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- LobeHub ([#14441](https://github.com/community-scripts/ProxmoxVE/pull/14441))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- Update nodejs Versions [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14582](https://github.com/community-scripts/ProxmoxVE/pull/14582))
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- ESPConnect: Fix paths to SSL certificates [@tremor021](https://github.com/tremor021) ([#14591](https://github.com/community-scripts/ProxmoxVE/pull/14591))
|
||||||
|
- ReactiveResume: set correct WorkingDirectory for systemd service [@MickLesk](https://github.com/MickLesk) ([#14579](https://github.com/community-scripts/ProxmoxVE/pull/14579))
|
||||||
|
- Sparkyfitness: add missing nginx template variable substitutions [@MickLesk](https://github.com/MickLesk) ([#14578](https://github.com/community-scripts/ProxmoxVE/pull/14578))
|
||||||
|
- Wanderer: include dev dependencies during build [@MickLesk](https://github.com/MickLesk) ([#14577](https://github.com/community-scripts/ProxmoxVE/pull/14577))
|
||||||
|
- Whisparr: switch from nightly to stable GitHub release [@MickLesk](https://github.com/MickLesk) ([#14581](https://github.com/community-scripts/ProxmoxVE/pull/14581))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Refactor: SonarQube [@tremor021](https://github.com/tremor021) ([#14594](https://github.com/community-scripts/ProxmoxVE/pull/14594))
|
||||||
|
|
||||||
|
## 2026-05-18
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- ESPconnect ([#14444](https://github.com/community-scripts/ProxmoxVE/pull/14444))
|
||||||
|
- degoog ([#14533](https://github.com/community-scripts/ProxmoxVE/pull/14533))
|
||||||
|
- Webtrees ([#14532](https://github.com/community-scripts/ProxmoxVE/pull/14532))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Bichon: Support v1 migration [@tomfrenzel](https://github.com/tomfrenzel) ([#14524](https://github.com/community-scripts/ProxmoxVE/pull/14524))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Pangolin: bump to 1.18.4, fix missing statusHistory migration [@MickLesk](https://github.com/MickLesk) ([#14566](https://github.com/community-scripts/ProxmoxVE/pull/14566))
|
||||||
|
|
||||||
|
## 2026-05-17
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- dashy: fix yarn-missing on update and back up full user-data [@lissy93](https://github.com/lissy93) ([#14548](https://github.com/community-scripts/ProxmoxVE/pull/14548))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: replace max-time with speed-limit stall detection in curl_download [@MickLesk](https://github.com/MickLesk) ([#14545](https://github.com/community-scripts/ProxmoxVE/pull/14545))
|
||||||
|
|
||||||
## 2026-05-16
|
## 2026-05-16
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|||||||
18
.github/workflows/check-node-versions.yml
generated
vendored
18
.github/workflows/check-node-versions.yml
generated
vendored
@@ -336,14 +336,18 @@ jobs:
|
|||||||
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
||||||
drift_count=$((drift_count + 1))
|
drift_count=$((drift_count + 1))
|
||||||
elif [[ -n "$upstream_major" && "$our_version" != "$upstream_major" ]]; then
|
elif [[ -n "$upstream_major" && "$our_version" != "$upstream_major" ]]; then
|
||||||
# Check if engines.node is a minimum constraint that our version satisfies
|
if (( our_version < upstream_major )); then
|
||||||
if [[ -z "$DF_NODE_MAJOR" && "$ENGINES_IS_MINIMUM" == "true" ]] && \
|
# Check if engines.node is a minimum constraint that our version satisfies
|
||||||
version_satisfies_engines "$our_version" "$ENGINES_MIN_MAJOR" "$ENGINES_IS_MINIMUM"; then
|
if [[ -z "$DF_NODE_MAJOR" && "$ENGINES_IS_MINIMUM" == "true" ]] && \
|
||||||
status="✅ (engines: $ENGINES_NODE_RAW — ours: $our_version satisfies)"
|
version_satisfies_engines "$our_version" "$ENGINES_MIN_MAJOR" "$ENGINES_IS_MINIMUM"; then
|
||||||
|
status="✅ (engines: $ENGINES_NODE_RAW — ours: $our_version satisfies)"
|
||||||
|
else
|
||||||
|
status="🔸 Drift → upstream=$upstream_major ($upstream_hint)"
|
||||||
|
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
||||||
|
drift_count=$((drift_count + 1))
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
status="🔸 Drift → upstream=$upstream_major ($upstream_hint)"
|
status="✅ Ahead of upstream ($upstream_major via $upstream_hint)"
|
||||||
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
|
||||||
drift_count=$((drift_count + 1))
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
71
.github/workflows/close-new-script-prs.yml
generated
vendored
71
.github/workflows/close-new-script-prs.yml
generated
vendored
@@ -3,7 +3,7 @@ name: Close Unauthorized New Script PRs
|
|||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
branches: ["main"]
|
branches: ["main"]
|
||||||
types: [opened, labeled]
|
types: [opened, labeled, reopened, synchronize]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-new-script:
|
check-new-script:
|
||||||
@@ -24,13 +24,6 @@ jobs:
|
|||||||
const owner = context.repo.owner;
|
const owner = context.repo.owner;
|
||||||
const repo = context.repo.repo;
|
const repo = context.repo.repo;
|
||||||
|
|
||||||
// --- Only act on PRs with the "new script" label ---
|
|
||||||
const labels = pr.labels.map(l => l.name);
|
|
||||||
if (!labels.includes("new script")) {
|
|
||||||
core.info(`PR #${prNumber} does not have "new script" label — skipping.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Allow our bots ---
|
// --- Allow our bots ---
|
||||||
const allowedBots = [
|
const allowedBots = [
|
||||||
"push-app-to-main[bot]",
|
"push-app-to-main[bot]",
|
||||||
@@ -42,38 +35,40 @@ jobs:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Check if author is a member of the contributor team ---
|
// --- Exempt contributors via author_association ---
|
||||||
const teamSlug = "contributor";
|
// OWNER/MEMBER/COLLABORATOR are trusted; CONTRIBUTOR ("has merged before")
|
||||||
let isMember = false;
|
// and NONE are not — their new-script PRs are still closed.
|
||||||
|
const association = pr.author_association;
|
||||||
try {
|
const exempt = ["OWNER", "MEMBER", "COLLABORATOR"];
|
||||||
const { status } = await github.rest.teams.getMembershipForUserInOrg({
|
if (exempt.includes(association)) {
|
||||||
org: owner,
|
core.info(`PR #${prNumber} by ${association} "${author}" — skipping.`);
|
||||||
team_slug: teamSlug,
|
return;
|
||||||
username: author,
|
|
||||||
});
|
|
||||||
// status 200 means the user is a member (active or pending)
|
|
||||||
isMember = true;
|
|
||||||
} catch (error) {
|
|
||||||
if (error.status === 404) {
|
|
||||||
isMember = false;
|
|
||||||
} else {
|
|
||||||
core.warning(`Could not check team membership for ${author}: ${error.message}`);
|
|
||||||
// Fallback: check org membership
|
|
||||||
try {
|
|
||||||
await github.rest.orgs.checkMembershipForUser({
|
|
||||||
org: owner,
|
|
||||||
username: author,
|
|
||||||
});
|
|
||||||
isMember = true;
|
|
||||||
} catch {
|
|
||||||
isMember = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMember) {
|
// --- Detect a new-script PR: "new script" label OR a newly-added
|
||||||
core.info(`PR #${prNumber} by contributor "${author}" — skipping.`);
|
// script file under ct/ install/ turnkey/ vm/ (mirrors
|
||||||
|
// autolabeler-config.json). Removes the label-timing dependency. ---
|
||||||
|
const labels = pr.labels.map(l => l.name);
|
||||||
|
const hasNewScriptLabel = labels.includes("new script");
|
||||||
|
|
||||||
|
const scriptPrefixes = ["ct/", "install/", "turnkey/", "vm/"];
|
||||||
|
let hasAddedScriptFile = false;
|
||||||
|
try {
|
||||||
|
const files = await github.paginate(github.rest.pulls.listFiles, {
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
pull_number: prNumber,
|
||||||
|
per_page: 100,
|
||||||
|
});
|
||||||
|
hasAddedScriptFile = files.some(
|
||||||
|
f => f.status === "added" && scriptPrefixes.some(p => f.filename.startsWith(p))
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Could not list files for PR #${prNumber}: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasNewScriptLabel && !hasAddedScriptFile) {
|
||||||
|
core.info(`PR #${prNumber} is not a new-script submission (no label, no added script file) — skipping.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
71
.github/workflows/close_issue_in_dev.yaml
generated
vendored
71
.github/workflows/close_issue_in_dev.yaml
generated
vendored
@@ -56,46 +56,57 @@ jobs:
|
|||||||
echo "$slugs" > pocketbase_slugs.txt
|
echo "$slugs" > pocketbase_slugs.txt
|
||||||
echo "count=$(echo $slugs | wc -w)" >> "$GITHUB_OUTPUT"
|
echo "count=$(echo $slugs | wc -w)" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Search for Issues with Similar Titles
|
- name: Find matching issues in ProxmoxVED by slug
|
||||||
id: find_issue
|
id: find_issue
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
issues=$(gh issue list --repo community-scripts/ProxmoxVED --json number,title --jq '.[] | {number, title}')
|
if [[ ! -s pocketbase_slugs.txt ]]; then
|
||||||
|
echo "No slugs derived from PR — nothing to match."
|
||||||
best_match_score=0
|
echo "issue_numbers=" >> "$GITHUB_OUTPUT"
|
||||||
best_match_number=0
|
|
||||||
|
|
||||||
for issue in $(echo "$issues" | jq -r '. | @base64'); do
|
|
||||||
_jq() {
|
|
||||||
echo ${issue} | base64 --decode | jq -r ${1}
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_title=$(_jq '.title' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g')
|
|
||||||
issue_number=$(_jq '.number')
|
|
||||||
|
|
||||||
match_score=$(echo "$title" | grep -o "$issue_title" | wc -l)
|
|
||||||
|
|
||||||
if [ "$match_score" -gt "$best_match_score" ]; then
|
|
||||||
best_match_score=$match_score
|
|
||||||
best_match_number=$issue_number
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$best_match_number" != "0" ]; then
|
|
||||||
echo "issue_number=$best_match_number" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "No matching issue found."
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
slugs=$(cat pocketbase_slugs.txt)
|
||||||
|
|
||||||
- name: Comment on the Best-Matching Issue and Close It
|
# Normalize: lowercase, strip spaces and hyphens (same shape as the slug derivation)
|
||||||
if: env.issue_number != ''
|
norm() { echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[[:space:]]//g; s/-//g'; }
|
||||||
|
|
||||||
|
issues=$(gh issue list --repo community-scripts/ProxmoxVED --state open --limit 1000 --json number,title,body)
|
||||||
|
|
||||||
|
matched=""
|
||||||
|
for slug in $slugs; do
|
||||||
|
nslug=$(norm "$slug")
|
||||||
|
[[ -z "$nslug" ]] && continue
|
||||||
|
while IFS= read -r row; do
|
||||||
|
num=$(echo "$row" | jq -r '.number')
|
||||||
|
ntitle=$(norm "$(echo "$row" | jq -r '.title')")
|
||||||
|
body=$(echo "$row" | jq -r '.body // ""' | tr '[:upper:]' '[:lower:]')
|
||||||
|
# Match when the issue title contains the slug, or the body mentions it verbatim
|
||||||
|
if [[ "$ntitle" == *"$nslug"* ]] || [[ "$body" == *"$slug"* ]]; then
|
||||||
|
matched="$matched $num"
|
||||||
|
fi
|
||||||
|
done < <(echo "$issues" | jq -c '.[]')
|
||||||
|
done
|
||||||
|
|
||||||
|
matched=$(echo $matched | xargs -n1 2>/dev/null | sort -un | tr '\n' ' ')
|
||||||
|
if [[ -z "$matched" ]]; then
|
||||||
|
echo "No matching ProxmoxVED issues found for slugs: $slugs"
|
||||||
|
echo "issue_numbers=" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Matched ProxmoxVED issues: $matched"
|
||||||
|
echo "issue_numbers=$matched" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Comment on and close matching ProxmoxVED issues
|
||||||
|
if: steps.find_issue.outputs.issue_numbers != ''
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.PAT_MICHEL }}
|
GH_TOKEN: ${{ secrets.PAT_MICHEL }}
|
||||||
run: |
|
run: |
|
||||||
gh issue comment $issue_number --repo community-scripts/ProxmoxVED --body "Merged with #${{ github.event.pull_request.number }} in ProxmoxVE"
|
for issue_number in ${{ steps.find_issue.outputs.issue_numbers }}; do
|
||||||
gh issue close $issue_number --repo community-scripts/ProxmoxVED
|
echo "Closing ProxmoxVED issue #$issue_number"
|
||||||
|
gh issue comment "$issue_number" --repo community-scripts/ProxmoxVED --body "Merged with #${{ github.event.pull_request.number }} in ProxmoxVE"
|
||||||
|
gh issue close "$issue_number" --repo community-scripts/ProxmoxVED
|
||||||
|
done
|
||||||
|
|
||||||
- name: Set is_dev to false in PocketBase
|
- name: Set is_dev to false in PocketBase
|
||||||
if: steps.get_slugs.outputs.count != '0'
|
if: steps.get_slugs.outputs.count != '0'
|
||||||
|
|||||||
4
.github/workflows/lock-issue.yaml
generated
vendored
4
.github/workflows/lock-issue.yaml
generated
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const daysBeforeLock = 3;
|
const daysBeforeLock = 7;
|
||||||
const lockDate = new Date();
|
const lockDate = new Date();
|
||||||
lockDate.setDate(lockDate.getDate() - daysBeforeLock);
|
lockDate.setDate(lockDate.getDate() - daysBeforeLock);
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
/dependabot/i
|
/dependabot/i
|
||||||
];
|
];
|
||||||
|
|
||||||
// Search for closed, unlocked issues older than 3 days (paginated, oldest first)
|
// Search for closed, unlocked issues older than 7 days (paginated, oldest first)
|
||||||
let page = 1;
|
let page = 1;
|
||||||
let totalLocked = 0;
|
let totalLocked = 0;
|
||||||
|
|
||||||
|
|||||||
610
.github/workflows/pocketbase-ai-bot.yml
generated
vendored
Normal file
610
.github/workflows/pocketbase-ai-bot.yml
generated
vendored
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
name: PocketBase AI Bot
|
||||||
|
|
||||||
|
# Natural-language companion to pocketbase-bot.yml.
|
||||||
|
# Mention the bot in plain English, e.g.:
|
||||||
|
# @pocketbase-bot change RAM to 4096 on zigbee2mqtt
|
||||||
|
# @pocketbase-bot disable script Nextcloud because upstream is broken
|
||||||
|
# The bot parses the request with GitHub Models, replies with the exact change(s)
|
||||||
|
# it understood, and only applies them after you reply "@pocketbase-bot confirm".
|
||||||
|
# The slash-command bot (/pocketbase ...) is unaffected; triggers do not overlap.
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
models: read # lets the built-in GITHUB_TOKEN call GitHub Models inference
|
||||||
|
contents: write # built-in token opens the CT-defaults sync PR (like the slash bot)
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ai-bot:
|
||||||
|
runs-on: self-hosted
|
||||||
|
# Broad gate; the script does precise keyword + self-author checks.
|
||||||
|
if: contains(github.event.comment.body, '@pocketbase-bot')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Mint GitHub App token (bot identity)
|
||||||
|
id: app-token
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.PB_BOT_APP_ID }}
|
||||||
|
private-key: ${{ secrets.PB_BOT_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Run PocketBase AI bot
|
||||||
|
env:
|
||||||
|
# GitHub REST as the bot identity
|
||||||
|
GH_APP_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||||
|
PB_BOT_APP_ID: ${{ secrets.PB_BOT_APP_ID }}
|
||||||
|
# GitHub Models inference uses the built-in token (needs models: read)
|
||||||
|
MODELS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Built-in token for git/PR ops (CT-defaults sync), mirroring the slash bot
|
||||||
|
GH_DEFAULT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
AI_MODEL: openai/gpt-4o
|
||||||
|
# PocketBase
|
||||||
|
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
|
||||||
|
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
|
||||||
|
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
|
||||||
|
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
|
||||||
|
FRONTEND_URL: ${{ secrets.FRONTEND_URL }}
|
||||||
|
REVALIDATE_SECRET: ${{ secrets.REVALIDATE_SECRET }}
|
||||||
|
# Event context
|
||||||
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||||
|
COMMENT_ID: ${{ github.event.comment.id }}
|
||||||
|
COMMENT_AUTHOR_TYPE: ${{ github.event.comment.user.type }}
|
||||||
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||||
|
REPO_OWNER: ${{ github.repository_owner }}
|
||||||
|
REPO_NAME: ${{ github.event.repository.name }}
|
||||||
|
ACTOR: ${{ github.event.comment.user.login }}
|
||||||
|
ACTOR_ASSOCIATION: ${{ github.event.comment.author_association }}
|
||||||
|
run: |
|
||||||
|
node << 'ENDSCRIPT'
|
||||||
|
(async function () {
|
||||||
|
const https = require('https');
|
||||||
|
const http = require('http');
|
||||||
|
const url = require('url');
|
||||||
|
|
||||||
|
// ── HTTP helper with redirect following ────────────────────────────
|
||||||
|
function request(fullUrl, opts, redirectCount) {
|
||||||
|
redirectCount = redirectCount || 0;
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
const u = url.parse(fullUrl);
|
||||||
|
const isHttps = u.protocol === 'https:';
|
||||||
|
const body = opts.body;
|
||||||
|
const options = {
|
||||||
|
hostname: u.hostname,
|
||||||
|
port: u.port || (isHttps ? 443 : 80),
|
||||||
|
path: u.path,
|
||||||
|
method: opts.method || 'GET',
|
||||||
|
headers: opts.headers || {}
|
||||||
|
};
|
||||||
|
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||||
|
const lib = isHttps ? https : http;
|
||||||
|
const req = lib.request(options, function (res) {
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||||
|
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||||
|
res.resume();
|
||||||
|
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = '';
|
||||||
|
res.on('data', function (chunk) { data += chunk; });
|
||||||
|
res.on('end', function () {
|
||||||
|
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
req.on('error', reject);
|
||||||
|
if (body) req.write(body);
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── GitHub REST (as the bot app) ───────────────────────────────────
|
||||||
|
const owner = process.env.REPO_OWNER;
|
||||||
|
const repo = process.env.REPO_NAME;
|
||||||
|
const issueNumber = parseInt(process.env.ISSUE_NUMBER, 10);
|
||||||
|
const commentId = parseInt(process.env.COMMENT_ID, 10);
|
||||||
|
const actor = process.env.ACTOR;
|
||||||
|
|
||||||
|
function ghRequest(path, method, body) {
|
||||||
|
const headers = {
|
||||||
|
'Authorization': 'Bearer ' + process.env.GH_APP_TOKEN,
|
||||||
|
'Accept': 'application/vnd.github+json',
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28',
|
||||||
|
'User-Agent': 'PocketBase-AI-Bot'
|
||||||
|
};
|
||||||
|
const bodyStr = body ? JSON.stringify(body) : undefined;
|
||||||
|
if (bodyStr) headers['Content-Type'] = 'application/json';
|
||||||
|
return request('https://api.github.com' + path, { method: method || 'GET', headers, body: bodyStr });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as ghRequest but authenticated with the built-in GITHUB_TOKEN.
|
||||||
|
// Used for the CT-defaults sync branch/PR (the App token lacks contents:write).
|
||||||
|
function ghDefault(path, method, body) {
|
||||||
|
const headers = {
|
||||||
|
'Authorization': 'Bearer ' + process.env.GH_DEFAULT_TOKEN,
|
||||||
|
'Accept': 'application/vnd.github+json',
|
||||||
|
'X-GitHub-Api-Version': '2022-11-28',
|
||||||
|
'User-Agent': 'PocketBase-AI-Bot'
|
||||||
|
};
|
||||||
|
const bodyStr = body ? JSON.stringify(body) : undefined;
|
||||||
|
if (bodyStr) headers['Content-Type'] = 'application/json';
|
||||||
|
return request('https://api.github.com' + path, { method: method || 'GET', headers, body: bodyStr });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addReaction(content) {
|
||||||
|
try {
|
||||||
|
await ghRequest('/repos/' + owner + '/' + repo + '/issues/comments/' + commentId + '/reactions', 'POST', { content });
|
||||||
|
} catch (e) { console.warn('Could not add reaction:', e.message); }
|
||||||
|
}
|
||||||
|
async function postComment(text) {
|
||||||
|
const res = await ghRequest('/repos/' + owner + '/' + repo + '/issues/' + issueNumber + '/comments', 'POST', { body: text });
|
||||||
|
if (!res.ok) console.warn('Could not post comment:', res.body);
|
||||||
|
return res.ok ? JSON.parse(res.body) : null;
|
||||||
|
}
|
||||||
|
async function updateComment(id, text) {
|
||||||
|
const res = await ghRequest('/repos/' + owner + '/' + repo + '/issues/comments/' + id, 'PATCH', { body: text });
|
||||||
|
if (!res.ok) console.warn('Could not update comment:', res.body);
|
||||||
|
}
|
||||||
|
async function listIssueComments() {
|
||||||
|
const all = [];
|
||||||
|
let page = 1;
|
||||||
|
while (page <= 10) {
|
||||||
|
const res = await ghRequest('/repos/' + owner + '/' + repo + '/issues/' + issueNumber + '/comments?per_page=100&page=' + page);
|
||||||
|
if (!res.ok) break;
|
||||||
|
const batch = JSON.parse(res.body);
|
||||||
|
all.push.apply(all, batch);
|
||||||
|
if (batch.length < 100) break;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 1. Self-trigger guard (App-token comments DO re-fire this event) ─
|
||||||
|
if (process.env.COMMENT_AUTHOR_TYPE === 'Bot') {
|
||||||
|
console.log('Comment authored by a bot — skipping to avoid loops.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 2. Permission gate (mirrors the slash bot) ─────────────────────
|
||||||
|
const association = process.env.ACTOR_ASSOCIATION;
|
||||||
|
if (association !== 'OWNER' && association !== 'MEMBER') {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'❌ **PocketBase AI Bot**: @' + actor + ' is not authorized to use this command.\n' +
|
||||||
|
'Only org members (Contributors team) can use `@pocketbase-bot`.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 3. Extract the instruction after the @pocketbase-bot handle ────
|
||||||
|
const commentBody = process.env.COMMENT_BODY || '';
|
||||||
|
const handleMatch = commentBody.match(/@pocketbase-bot(\[bot\])?/i);
|
||||||
|
if (!handleMatch) {
|
||||||
|
console.log('No @pocketbase-bot handle found — ignoring.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const instruction = commentBody.slice(handleMatch.index + handleMatch[0].length).trim();
|
||||||
|
if (!instruction) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment(
|
||||||
|
'ℹ️ **PocketBase AI Bot**: Tell me what to do, e.g.\n' +
|
||||||
|
'`@pocketbase-bot change RAM to 4096 on zigbee2mqtt` or `@pocketbase-bot disable script Nextcloud`.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── PocketBase auth + low-level helpers ────────────────────────────
|
||||||
|
const pbRaw = process.env.POCKETBASE_URL.replace(/\/$/, '');
|
||||||
|
const apiBase = /\/api$/i.test(pbRaw) ? pbRaw : pbRaw + '/api';
|
||||||
|
const coll = process.env.POCKETBASE_COLLECTION;
|
||||||
|
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
|
||||||
|
|
||||||
|
async function pbAuth() {
|
||||||
|
const res = await request(apiBase + '/collections/users/auth-with-password', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ identity: process.env.POCKETBASE_ADMIN_EMAIL, password: process.env.POCKETBASE_ADMIN_PASSWORD })
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error('PocketBase auth failed: ' + res.body);
|
||||||
|
return JSON.parse(res.body).token;
|
||||||
|
}
|
||||||
|
async function pbFindRecord(token, slug) {
|
||||||
|
const filter = "(slug='" + String(slug).replace(/'/g, "''") + "')";
|
||||||
|
const res = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', { headers: { 'Authorization': token } });
|
||||||
|
const list = JSON.parse(res.body);
|
||||||
|
return list.items && list.items[0];
|
||||||
|
}
|
||||||
|
async function pbPatch(token, id, payload) {
|
||||||
|
return request(recordsUrl + '/' + id, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function readJsonBlob(val) {
|
||||||
|
if (Array.isArray(val)) return val;
|
||||||
|
try { return JSON.parse(val || '[]'); } catch (e) { return []; }
|
||||||
|
}
|
||||||
|
async function revalidate(s) {
|
||||||
|
const frontendUrl = process.env.FRONTEND_URL;
|
||||||
|
const secret = process.env.REVALIDATE_SECRET;
|
||||||
|
if (!frontendUrl || !secret) return;
|
||||||
|
try {
|
||||||
|
await request(frontendUrl.replace(/\/$/, '') + '/api/revalidate', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Authorization': 'Bearer ' + secret, 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ tags: ['scripts', 'script-' + s] })
|
||||||
|
});
|
||||||
|
} catch (e) { console.warn('Revalidation skipped:', e.message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── CT-defaults sync PR (copied from slash bot) ────────────────────
|
||||||
|
function encodeContentPath(filePath) { return filePath.split('/').map(encodeURIComponent).join('/'); }
|
||||||
|
function decodeGitHubContent(content) { return Buffer.from((content || '').replace(/\n/g, ''), 'base64').toString('utf8'); }
|
||||||
|
function sanitizeBranchPart(value) {
|
||||||
|
return (value || '').toLowerCase().replace(/[^a-z0-9._/-]+/g, '-').replace(/\/+/g, '/').replace(/^-+|-+$/g, '');
|
||||||
|
}
|
||||||
|
function applyCtDefaultChanges(scriptText, varChanges) {
|
||||||
|
let nextText = scriptText;
|
||||||
|
const updatedVars = [], unchangedVars = [];
|
||||||
|
for (const [varName, rawValue] of Object.entries(varChanges)) {
|
||||||
|
const newValue = String(rawValue);
|
||||||
|
const pattern = new RegExp('(^\\s*' + varName + '="\\$\\{' + varName + ':-)([^"}]*)(\\}"\\s*$)', 'm');
|
||||||
|
const match = nextText.match(pattern);
|
||||||
|
if (!match) continue;
|
||||||
|
if (match[2] === newValue) { unchangedVars.push(varName); continue; }
|
||||||
|
nextText = nextText.replace(pattern, '$1' + newValue + '$3');
|
||||||
|
updatedVars.push(varName);
|
||||||
|
}
|
||||||
|
return { nextText, updatedVars, unchangedVars };
|
||||||
|
}
|
||||||
|
async function ensureBranch(defaultBranch, branchName) {
|
||||||
|
const ghRequest = ghDefault; // git ops run as the built-in token
|
||||||
|
const branchRefRes = await ghRequest('/repos/' + owner + '/' + repo + '/git/ref/heads/' + encodeURIComponent(branchName));
|
||||||
|
if (branchRefRes.ok) return;
|
||||||
|
const defaultRefRes = await ghRequest('/repos/' + owner + '/' + repo + '/git/ref/heads/' + encodeURIComponent(defaultBranch));
|
||||||
|
if (!defaultRefRes.ok) throw new Error('Could not read default branch ref: ' + defaultRefRes.body);
|
||||||
|
const defaultRef = JSON.parse(defaultRefRes.body);
|
||||||
|
const createBranchRes = await ghRequest('/repos/' + owner + '/' + repo + '/git/refs', 'POST', { ref: 'refs/heads/' + branchName, sha: defaultRef.object.sha });
|
||||||
|
if (!createBranchRes.ok) throw new Error('Could not create branch: ' + createBranchRes.body);
|
||||||
|
}
|
||||||
|
async function upsertCtDefaultsPr(slugValue, varChanges) {
|
||||||
|
const ghRequest = ghDefault; // contents/PR ops run as the built-in token
|
||||||
|
const wantedEntries = Object.entries(varChanges || {}).filter(function ([, v]) { return v !== undefined && v !== null && String(v) !== ''; });
|
||||||
|
if (wantedEntries.length === 0) return { status: 'skipped', reason: 'No mapped CT defaults changed.' };
|
||||||
|
const repoRes = await ghRequest('/repos/' + owner + '/' + repo);
|
||||||
|
if (!repoRes.ok) throw new Error('Could not read repository metadata: ' + repoRes.body);
|
||||||
|
const defaultBranch = JSON.parse(repoRes.body).default_branch;
|
||||||
|
const ctPath = 'ct/' + slugValue + '.sh';
|
||||||
|
const encodedCtPath = encodeContentPath(ctPath);
|
||||||
|
const defaultFileRes = await ghRequest('/repos/' + owner + '/' + repo + '/contents/' + encodedCtPath + '?ref=' + encodeURIComponent(defaultBranch));
|
||||||
|
if (defaultFileRes.statusCode === 404) return { status: 'skipped', reason: 'No matching CT file found at `' + ctPath + '`.' };
|
||||||
|
if (!defaultFileRes.ok) throw new Error('Could not read CT file from default branch: ' + defaultFileRes.body);
|
||||||
|
const branchName = 'pocketbase-sync/' + sanitizeBranchPart(slugValue || 'unknown');
|
||||||
|
await ensureBranch(defaultBranch, branchName);
|
||||||
|
const branchFileRes = await ghRequest('/repos/' + owner + '/' + repo + '/contents/' + encodedCtPath + '?ref=' + encodeURIComponent(branchName));
|
||||||
|
if (!branchFileRes.ok) throw new Error('Could not read CT file from sync branch: ' + branchFileRes.body);
|
||||||
|
const branchFile = JSON.parse(branchFileRes.body);
|
||||||
|
const currentBranchText = decodeGitHubContent(branchFile.content);
|
||||||
|
const updateResult = applyCtDefaultChanges(currentBranchText, Object.fromEntries(wantedEntries));
|
||||||
|
if (updateResult.updatedVars.length === 0) return { status: 'skipped', reason: 'CT defaults already up to date.' };
|
||||||
|
const putRes = await ghRequest('/repos/' + owner + '/' + repo + '/contents/' + encodedCtPath, 'PUT', {
|
||||||
|
message: 'chore(ct): sync ' + slugValue + ' defaults from PocketBase',
|
||||||
|
content: Buffer.from(updateResult.nextText, 'utf8').toString('base64'),
|
||||||
|
sha: branchFile.sha,
|
||||||
|
branch: branchName
|
||||||
|
});
|
||||||
|
if (!putRes.ok) throw new Error('Could not update CT file: ' + putRes.body);
|
||||||
|
const openPrRes = await ghRequest('/repos/' + owner + '/' + repo + '/pulls?state=open&head=' + encodeURIComponent(owner + ':' + branchName) + '&base=' + encodeURIComponent(defaultBranch));
|
||||||
|
if (!openPrRes.ok) throw new Error('Could not query existing PRs: ' + openPrRes.body);
|
||||||
|
const openPrs = JSON.parse(openPrRes.body);
|
||||||
|
if (openPrs.length > 0) return { status: 'updated', prUrl: openPrs[0].html_url, updatedVars: updateResult.updatedVars };
|
||||||
|
const createPrRes = await ghRequest('/repos/' + owner + '/' + repo + '/pulls', 'POST', {
|
||||||
|
title: 'chore(ct): sync ' + slugValue + ' defaults with PocketBase',
|
||||||
|
body: '## Summary\n- Sync default CT variables for `' + slugValue + '` after an `@pocketbase-bot` update.\n- Updated vars: `' + updateResult.updatedVars.join('`, `') + '`.\n\n## Source\n- Triggered by @' + actor + ' via PocketBase AI bot.\n',
|
||||||
|
head: branchName,
|
||||||
|
base: defaultBranch
|
||||||
|
});
|
||||||
|
if (!createPrRes.ok) throw new Error('Could not create PR: ' + createPrRes.body);
|
||||||
|
return { status: 'created', prUrl: JSON.parse(createPrRes.body).html_url, updatedVars: updateResult.updatedVars };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Allow-lists (mirror the slash bot) ─────────────────────────────
|
||||||
|
const ALLOWED_FIELDS = {
|
||||||
|
name: 'string', description: 'string', logo: 'string', documentation: 'string',
|
||||||
|
website: 'string', project_url: 'string', github: 'string', config_path: 'string',
|
||||||
|
tags: 'string', port: 'number', default_user: 'nullable_string', default_passwd: 'nullable_string',
|
||||||
|
unprivileged: 'number', updateable: 'boolean', privileged: 'boolean', has_arm: 'boolean',
|
||||||
|
is_dev: 'boolean', is_disabled: 'boolean', disable_message: 'string',
|
||||||
|
is_deleted: 'boolean', deleted_message: 'string'
|
||||||
|
};
|
||||||
|
const FIELD_TO_CT_VAR = { tags: 'var_tags', unprivileged: 'var_unprivileged' };
|
||||||
|
const RESOURCE_KEYS = { cpu: 'number', ram: 'number', hdd: 'number', os: 'string', version: 'string' };
|
||||||
|
const METHOD_KEYS = { config_path: 'string', script: 'string' };
|
||||||
|
const ALL_METHOD_KEYS = Object.assign({}, RESOURCE_KEYS, METHOD_KEYS);
|
||||||
|
const RESOURCE_TO_CT_VAR = { cpu: 'var_cpu', ram: 'var_ram', hdd: 'var_disk', os: 'var_os', version: 'var_version' };
|
||||||
|
|
||||||
|
function castFieldValue(key, rawVal) {
|
||||||
|
const type = ALLOWED_FIELDS[key];
|
||||||
|
if (!type) return { error: 'Unknown field `' + key + '`' };
|
||||||
|
if (type === 'boolean') {
|
||||||
|
if (rawVal === true || rawVal === 'true') return { value: true };
|
||||||
|
if (rawVal === false || rawVal === 'false') return { value: false };
|
||||||
|
return { error: '`' + key + '` must be true/false' };
|
||||||
|
}
|
||||||
|
if (type === 'number') {
|
||||||
|
const n = parseInt(rawVal, 10);
|
||||||
|
if (isNaN(n)) return { error: '`' + key + '` must be a number' };
|
||||||
|
return { value: n };
|
||||||
|
}
|
||||||
|
if (type === 'nullable_string') return { value: rawVal === '' || rawVal == null ? null : String(rawVal) };
|
||||||
|
return { value: String(rawVal) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Operation validation (used at propose AND confirm time) ────────
|
||||||
|
// Never trust raw operations: enforce the field/op allow-lists and
|
||||||
|
// re-cast values. Returns only well-formed, allowed operations.
|
||||||
|
function sanitizeOperations(ops) {
|
||||||
|
const validOps = [], problems = [];
|
||||||
|
for (const op of (Array.isArray(ops) ? ops : [])) {
|
||||||
|
if (op && op.kind === 'field') {
|
||||||
|
const cast = castFieldValue(op.field, op.value);
|
||||||
|
if (cast.error) { problems.push(cast.error); continue; }
|
||||||
|
validOps.push({ kind: 'field', field: op.field, value: cast.value });
|
||||||
|
} else if (op && op.kind === 'note' && ['add', 'edit', 'remove'].includes(op.action)) {
|
||||||
|
validOps.push({ kind: 'note', action: op.action, type: String(op.type || ''), text: op.text, newText: op.newText });
|
||||||
|
} else if (op && op.kind === 'method' && ['add', 'edit', 'remove'].includes(op.action)) {
|
||||||
|
const changes = {};
|
||||||
|
for (const [k, v] of Object.entries(op.changes || {})) { if (ALL_METHOD_KEYS[k]) changes[k] = v; }
|
||||||
|
validOps.push({ kind: 'method', action: op.action, type: String(op.type || 'default'), changes });
|
||||||
|
} else {
|
||||||
|
problems.push('Unsupported operation: `' + JSON.stringify(op) + '`');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { validOps, problems };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Executor: apply a validated {slug, operations} set ─────────────
|
||||||
|
async function applyOperations(action) {
|
||||||
|
const token = await pbAuth();
|
||||||
|
const record = await pbFindRecord(token, action.slug);
|
||||||
|
if (!record) return { ok: false, summary: '❌ No PocketBase record for slug `' + action.slug + '`.' };
|
||||||
|
|
||||||
|
const fieldPayload = {};
|
||||||
|
let notesArr = readJsonBlob(record.notes);
|
||||||
|
let methodsArr = readJsonBlob(record.install_methods);
|
||||||
|
let notesChanged = false, methodsChanged = false;
|
||||||
|
const ctChanges = {};
|
||||||
|
const lines = [];
|
||||||
|
|
||||||
|
for (const op of action.operations) {
|
||||||
|
if (op.kind === 'field') {
|
||||||
|
const cast = castFieldValue(op.field, op.value);
|
||||||
|
if (cast.error) { lines.push('- ⚠️ skipped field: ' + cast.error); continue; }
|
||||||
|
fieldPayload[op.field] = cast.value;
|
||||||
|
if (FIELD_TO_CT_VAR[op.field]) ctChanges[FIELD_TO_CT_VAR[op.field]] = cast.value;
|
||||||
|
lines.push('- `' + op.field + '` → `' + JSON.stringify(cast.value) + '`');
|
||||||
|
} else if (op.kind === 'note') {
|
||||||
|
const type = String(op.type || '').toLowerCase();
|
||||||
|
if (op.action === 'add') {
|
||||||
|
notesArr.push({ type, text: String(op.text || '') });
|
||||||
|
notesChanged = true; lines.push('- note add `' + type + '`: ' + op.text);
|
||||||
|
} else if (op.action === 'remove') {
|
||||||
|
const before = notesArr.length;
|
||||||
|
notesArr = notesArr.filter(function (n) { return !(String(n.type).toLowerCase() === type && n.text === op.text); });
|
||||||
|
if (notesArr.length !== before) { notesChanged = true; lines.push('- note remove `' + type + '`: ' + op.text); }
|
||||||
|
else lines.push('- ⚠️ note remove: no `' + type + '` note matched');
|
||||||
|
} else if (op.action === 'edit') {
|
||||||
|
const idx = notesArr.findIndex(function (n) { return String(n.type).toLowerCase() === type && n.text === op.text; });
|
||||||
|
if (idx !== -1) { notesArr[idx].text = String(op.newText || ''); notesChanged = true; lines.push('- note edit `' + type + '`'); }
|
||||||
|
else lines.push('- ⚠️ note edit: no `' + type + '` note matched');
|
||||||
|
}
|
||||||
|
} else if (op.kind === 'method') {
|
||||||
|
const type = String(op.type || '').toLowerCase();
|
||||||
|
const changes = op.changes || {};
|
||||||
|
if (op.action === 'remove') {
|
||||||
|
const before = methodsArr.length;
|
||||||
|
methodsArr = methodsArr.filter(function (im) { return String(im.type || '').toLowerCase() !== type; });
|
||||||
|
if (methodsArr.length !== before) { methodsChanged = true; lines.push('- method remove `' + type + '`'); }
|
||||||
|
else lines.push('- ⚠️ method remove: `' + type + '` not found');
|
||||||
|
} else {
|
||||||
|
let method = methodsArr.find(function (im) { return String(im.type || '').toLowerCase() === type; });
|
||||||
|
if (!method && op.action === 'add') { method = { type, resources: { cpu: 1, ram: 512, hdd: 4, os: 'debian', version: '13' } }; methodsArr.push(method); }
|
||||||
|
if (!method) { lines.push('- ⚠️ method edit: `' + type + '` not found'); continue; }
|
||||||
|
if (!method.resources) method.resources = {};
|
||||||
|
for (const [k, v] of Object.entries(changes)) {
|
||||||
|
if (RESOURCE_KEYS[k]) {
|
||||||
|
method.resources[k] = RESOURCE_KEYS[k] === 'number' ? parseInt(v, 10) : String(v);
|
||||||
|
if (RESOURCE_TO_CT_VAR[k]) ctChanges[RESOURCE_TO_CT_VAR[k]] = method.resources[k];
|
||||||
|
} else if (METHOD_KEYS[k]) {
|
||||||
|
method[k] = v === '' ? null : String(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
methodsChanged = true;
|
||||||
|
lines.push('- method `' + (op.action === 'add' ? 'add' : 'edit') + '` `' + type + '`: ' + JSON.stringify(changes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(fieldPayload).length) {
|
||||||
|
const r = await pbPatch(token, record.id, fieldPayload);
|
||||||
|
if (!r.ok) return { ok: false, summary: '❌ Field update failed:\n```\n' + r.body + '\n```' };
|
||||||
|
}
|
||||||
|
if (notesChanged) {
|
||||||
|
const r = await pbPatch(token, record.id, { notes: notesArr });
|
||||||
|
if (!r.ok) return { ok: false, summary: '❌ Notes update failed:\n```\n' + r.body + '\n```' };
|
||||||
|
}
|
||||||
|
if (methodsChanged) {
|
||||||
|
const r = await pbPatch(token, record.id, { install_methods: methodsArr });
|
||||||
|
if (!r.ok) return { ok: false, summary: '❌ Install-method update failed:\n```\n' + r.body + '\n```' };
|
||||||
|
}
|
||||||
|
await revalidate(action.slug);
|
||||||
|
|
||||||
|
let ctNote = '';
|
||||||
|
if (Object.keys(ctChanges).length) {
|
||||||
|
try {
|
||||||
|
const sync = await upsertCtDefaultsPr(action.slug, ctChanges);
|
||||||
|
if (sync.status === 'created') ctNote = '\n\n**CT sync PR:** ' + sync.prUrl;
|
||||||
|
else if (sync.status === 'updated') ctNote = '\n\n**CT sync PR updated:** ' + sync.prUrl;
|
||||||
|
else if (sync.status === 'skipped') ctNote = '\n\n**CT sync skipped:** ' + sync.reason;
|
||||||
|
} catch (e) { ctNote = '\n\n**CT sync failed:** ' + e.message; }
|
||||||
|
}
|
||||||
|
return { ok: true, summary: lines.join('\n') + ctNote };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 4. Confirm branch ──────────────────────────────────────────────
|
||||||
|
const PENDING_RE = /<!--\s*pocketbase-pending:\s*([A-Za-z0-9+/=]+)\s*-->/;
|
||||||
|
const isConfirm = /^(confirm|yes|apply|do it|y)\b/i.test(instruction);
|
||||||
|
|
||||||
|
if (isConfirm) {
|
||||||
|
const comments = await listIssueComments();
|
||||||
|
const appId = String(process.env.PB_BOT_APP_ID || '');
|
||||||
|
let pending = null, pendingComment = null;
|
||||||
|
for (let i = comments.length - 1; i >= 0; i--) {
|
||||||
|
const c = comments[i];
|
||||||
|
// Only trust a marker in a comment THIS bot app authored — otherwise a
|
||||||
|
// user could hand-craft a forged pocketbase-pending marker and confirm it.
|
||||||
|
const byBotApp = c.user && c.user.type === 'Bot' &&
|
||||||
|
c.performed_via_github_app && String(c.performed_via_github_app.id) === appId;
|
||||||
|
if (!byBotApp) continue;
|
||||||
|
const m = c.body && c.body.match(PENDING_RE);
|
||||||
|
if (m) { pending = m[1]; pendingComment = c; break; }
|
||||||
|
}
|
||||||
|
if (!pending) {
|
||||||
|
await addReaction('confused');
|
||||||
|
await postComment('🤔 **PocketBase AI Bot**: I have no pending change to confirm in this thread.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let action;
|
||||||
|
try { action = JSON.parse(Buffer.from(pending, 'base64').toString('utf8')); }
|
||||||
|
catch (e) { await postComment('❌ **PocketBase AI Bot**: Could not decode the pending change.'); return; }
|
||||||
|
|
||||||
|
// Re-validate the decoded operations before applying (defense-in-depth).
|
||||||
|
const recheck = sanitizeOperations(action.operations);
|
||||||
|
if (!action.slug || recheck.validOps.length === 0) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase AI Bot**: The pending change is no longer valid. Please restate the request.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
action.operations = recheck.validOps;
|
||||||
|
|
||||||
|
let result;
|
||||||
|
try { result = await applyOperations(action); }
|
||||||
|
catch (e) { await addReaction('-1'); await postComment('❌ **PocketBase AI Bot**: ' + e.message); return; }
|
||||||
|
|
||||||
|
if (!result.ok) { await addReaction('-1'); await postComment(result.summary); return; }
|
||||||
|
await updateComment(pendingComment.id, pendingComment.body.replace(PENDING_RE, '<!-- pocketbase-applied -->'));
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'✅ **PocketBase AI Bot**: Applied to **`' + action.slug + '`**\n\n' + result.summary +
|
||||||
|
'\n\n*Confirmed by @' + actor + '*'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 5. New request: acknowledge, fetch script list, call the model ─
|
||||||
|
await addReaction('eyes');
|
||||||
|
|
||||||
|
const token0 = await pbAuth();
|
||||||
|
const scripts = [];
|
||||||
|
let page = 1;
|
||||||
|
while (page <= 5) {
|
||||||
|
const res = await request(recordsUrl + '?fields=slug,name&perPage=500&page=' + page, { headers: { 'Authorization': token0 } });
|
||||||
|
if (!res.ok) break;
|
||||||
|
const data = JSON.parse(res.body);
|
||||||
|
(data.items || []).forEach(function (it) { if (it.slug) scripts.push({ slug: it.slug, name: it.name || it.slug }); });
|
||||||
|
if (!data.items || data.items.length < 500) break;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SYSTEM_PROMPT =
|
||||||
|
'You translate a maintainer\'s natural-language request into a STRICT JSON change-set for a ' +
|
||||||
|
'script catalog (PocketBase). Respond with a SINGLE JSON object and nothing else.\n\n' +
|
||||||
|
'Schema:\n' +
|
||||||
|
'{\n' +
|
||||||
|
' "slug": string|null, // MUST be one of the known slugs below, chosen from the request\n' +
|
||||||
|
' "operations": [ ... ], // [] if you cannot determine concrete changes\n' +
|
||||||
|
' "human_summary": string, // short plain-English description\n' +
|
||||||
|
' "clarification": string|null // a question to ask if ambiguous/unsupported; else null\n' +
|
||||||
|
'}\n\n' +
|
||||||
|
'Operation kinds:\n' +
|
||||||
|
'- {"kind":"field","field":<one of: ' + Object.keys(ALLOWED_FIELDS).join(', ') + '>,"value":<bool|number|string>}\n' +
|
||||||
|
' (booleans true/false; "is_disabled"/"is_deleted"/"is_dev" are booleans; "port"/"unprivileged" are numbers; rest strings.)\n' +
|
||||||
|
'- {"kind":"note","action":"add"|"edit"|"remove","type":string,"text":string,"newText":string?}\n' +
|
||||||
|
'- {"kind":"method","action":"add"|"edit"|"remove","type":string,"changes":{cpu?:number,ram?:number,hdd?:number,os?:string,version?:string,config_path?:string,script?:string}}\n' +
|
||||||
|
' (RAM/HDD are in MB/GB; method "type" defaults to "default" if the user does not name one.)\n\n' +
|
||||||
|
'Rules:\n' +
|
||||||
|
'- Only use fields/operations listed above. If the request needs something else, set clarification and operations=[].\n' +
|
||||||
|
'- "disable"/"enable" map to is_disabled true/false. If disabling and the user gave a reason, also set disable_message.\n' +
|
||||||
|
'- Resolve the target script to a slug from the list. If you cannot confidently match exactly one, set slug=null and ask via clarification.\n\n' +
|
||||||
|
'Known scripts (slug — name):\n' +
|
||||||
|
scripts.map(function (s) { return s.slug + ' — ' + s.name; }).join('\n');
|
||||||
|
|
||||||
|
const modelRes = await request('https://models.github.ai/inference/chat/completions', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Authorization': 'Bearer ' + process.env.MODELS_TOKEN, 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: process.env.AI_MODEL || 'openai/gpt-4o',
|
||||||
|
temperature: 0.1,
|
||||||
|
response_format: { type: 'json_object' },
|
||||||
|
messages: [{ role: 'system', content: SYSTEM_PROMPT }, { role: 'user', content: instruction }]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if (!modelRes.ok) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase AI Bot**: Model request failed (' + modelRes.statusCode + ').\n```\n' + modelRes.body.slice(0, 500) + '\n```');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsed;
|
||||||
|
try {
|
||||||
|
const content = JSON.parse(modelRes.body).choices[0].message.content;
|
||||||
|
const cleaned = content.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
|
||||||
|
parsed = JSON.parse(cleaned);
|
||||||
|
} catch (e) {
|
||||||
|
await addReaction('-1');
|
||||||
|
await postComment('❌ **PocketBase AI Bot**: Could not parse the model response. Please rephrase.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 6. Validate ────────────────────────────────────────────────────
|
||||||
|
const knownSlugs = new Set(scripts.map(function (s) { return s.slug; }));
|
||||||
|
const problems = [];
|
||||||
|
if (parsed.clarification) problems.push(parsed.clarification);
|
||||||
|
if (!parsed.slug || !knownSlugs.has(parsed.slug)) problems.push('I could not match the request to a known script.');
|
||||||
|
const sanitized = sanitizeOperations(parsed.operations);
|
||||||
|
const validOps = sanitized.validOps;
|
||||||
|
problems.push.apply(problems, sanitized.problems);
|
||||||
|
if (validOps.length === 0) problems.push('No concrete, supported change was found.');
|
||||||
|
|
||||||
|
if (problems.length) {
|
||||||
|
await addReaction('confused');
|
||||||
|
await postComment(
|
||||||
|
'🤔 **PocketBase AI Bot**: I need a bit more to act on that.\n\n- ' + problems.join('\n- ') +
|
||||||
|
'\n\nTry naming the script and the exact change, e.g. `@pocketbase-bot set RAM to 4096 on zigbee2mqtt`.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 7. Propose (do NOT apply yet) ──────────────────────────────────
|
||||||
|
const action = { slug: parsed.slug, operations: validOps };
|
||||||
|
const bullets = validOps.map(function (op) {
|
||||||
|
if (op.kind === 'field') return '- `' + op.field + '` → `' + JSON.stringify(op.value) + '`';
|
||||||
|
if (op.kind === 'note') return '- note ' + op.action + ' `' + op.type + '`' + (op.text ? ': ' + op.text : '');
|
||||||
|
return '- method ' + op.action + ' `' + op.type + '`: ' + JSON.stringify(op.changes);
|
||||||
|
}).join('\n');
|
||||||
|
const marker = '<!-- pocketbase-pending: ' + Buffer.from(JSON.stringify(action), 'utf8').toString('base64') + ' -->';
|
||||||
|
await addReaction('+1');
|
||||||
|
await postComment(
|
||||||
|
'🤖 **PocketBase AI Bot** — please confirm\n\n' +
|
||||||
|
(parsed.human_summary ? '> ' + parsed.human_summary + '\n\n' : '') +
|
||||||
|
'**Target:** `' + action.slug + '`\n**Proposed changes:**\n' + bullets + '\n\n' +
|
||||||
|
'Reply **`@pocketbase-bot confirm`** to apply, or restate the request to adjust.\n' + marker
|
||||||
|
);
|
||||||
|
})().catch(function (e) {
|
||||||
|
console.error('Fatal error:', e && (e.message || e));
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
ENDSCRIPT
|
||||||
24
.github/workflows/pocketbase-bot.yml
generated
vendored
24
.github/workflows/pocketbase-bot.yml
generated
vendored
@@ -13,8 +13,8 @@ jobs:
|
|||||||
pocketbase-bot:
|
pocketbase-bot:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
|
|
||||||
# Only act on /pocketbase commands
|
# Act on comments that contain a /pocketbase command line (precise line check happens in-script)
|
||||||
if: startsWith(github.event.comment.body, '/pocketbase')
|
if: contains(github.event.comment.body, '/pocketbase')
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Execute PocketBase bot command
|
- name: Execute PocketBase bot command
|
||||||
@@ -257,6 +257,22 @@ jobs:
|
|||||||
if (!res.ok) console.warn('Could not post comment:', res.body);
|
if (!res.ok) console.warn('Could not post comment:', res.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Locate the command line ────────────────────────────────────────
|
||||||
|
// Accept /pocketbase at the start of ANY line (leading whitespace ok),
|
||||||
|
// so the command works even when preceded by other text. Mid-sentence
|
||||||
|
// mentions and blockquoted ("> ...") examples are ignored.
|
||||||
|
const commentBody = process.env.COMMENT_BODY || '';
|
||||||
|
const cmdLine = commentBody
|
||||||
|
.split('\n')
|
||||||
|
.map(l => l.trim())
|
||||||
|
.find(l => l.startsWith('/pocketbase'));
|
||||||
|
|
||||||
|
if (!cmdLine) {
|
||||||
|
console.log('No /pocketbase command line found — ignoring comment.');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
const withoutCmd = cmdLine.replace(/^\/pocketbase\s*/, '').trim();
|
||||||
|
|
||||||
// ── Permission check ───────────────────────────────────────────────
|
// ── Permission check ───────────────────────────────────────────────
|
||||||
const association = process.env.ACTOR_ASSOCIATION;
|
const association = process.env.ACTOR_ASSOCIATION;
|
||||||
if (association !== 'OWNER' && association !== 'MEMBER') {
|
if (association !== 'OWNER' && association !== 'MEMBER') {
|
||||||
@@ -272,10 +288,6 @@ jobs:
|
|||||||
await addReaction('eyes');
|
await addReaction('eyes');
|
||||||
|
|
||||||
// ── Parse command ──────────────────────────────────────────────────
|
// ── Parse command ──────────────────────────────────────────────────
|
||||||
const commentBody = process.env.COMMENT_BODY || '';
|
|
||||||
const lines = commentBody.trim().split('\n');
|
|
||||||
const firstLine = lines[0].trim();
|
|
||||||
const withoutCmd = firstLine.replace(/^\/pocketbase\s+/, '').trim();
|
|
||||||
|
|
||||||
function extractCodeBlock(body) {
|
function extractCodeBlock(body) {
|
||||||
const m = body.match(/```[^\n]*\n([\s\S]*?)```/);
|
const m = body.match(/```[^\n]*\n([\s\S]*?)```/);
|
||||||
|
|||||||
498
CHANGELOG.md
498
CHANGELOG.md
@@ -50,6 +50,12 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +72,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><h4>May (16 entries)</h4></summary>
|
<summary><h4>May (30 entries)</h4></summary>
|
||||||
|
|
||||||
[View May 2026 Changelog](.github/changelogs/2026/05.md)
|
[View May 2026 Changelog](.github/changelogs/2026/05.md)
|
||||||
|
|
||||||
@@ -464,6 +470,201 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
## 2026-06-02
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- infisical: fix update abort due to creds field mismatch (#14868) [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14870](https://github.com/community-scripts/ProxmoxVE/pull/14870))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- feat(degoog): enable default valkey cache integration [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14871](https://github.com/community-scripts/ProxmoxVE/pull/14871))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- chore: bump Node version in selected scripts [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14873](https://github.com/community-scripts/ProxmoxVE/pull/14873))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: add support for Rust installation profile in setup_rust [@MickLesk](https://github.com/MickLesk) ([#14872](https://github.com/community-scripts/ProxmoxVE/pull/14872))
|
||||||
|
|
||||||
|
### 📂 Github
|
||||||
|
|
||||||
|
- fix(workflow): only flag node drift when local is behind upstream [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14874](https://github.com/community-scripts/ProxmoxVE/pull/14874))
|
||||||
|
|
||||||
|
## 2026-06-01
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- fix(dispatcharr): forward nginx port for M3U URLs on new installs [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14862](https://github.com/community-scripts/ProxmoxVE/pull/14862))
|
||||||
|
- Set environment paths in service for apprise-api-install.sh [@SystemIdleProcess](https://github.com/SystemIdleProcess) ([#14805](https://github.com/community-scripts/ProxmoxVE/pull/14805))
|
||||||
|
- fix(fireshare): rebuild client on update to fix nginx 500 [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14848](https://github.com/community-scripts/ProxmoxVE/pull/14848))
|
||||||
|
- Fix Kan build failure (TS7016 nodemailer) [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14856](https://github.com/community-scripts/ProxmoxVE/pull/14856))
|
||||||
|
- fix(firefly): set Data Importer APP_URL for subdirectory install [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14847](https://github.com/community-scripts/ProxmoxVE/pull/14847))
|
||||||
|
- kan: extend fetch_and_deploy_gh_tag to use 'latest' tag [@MickLesk](https://github.com/MickLesk) ([#14853](https://github.com/community-scripts/ProxmoxVE/pull/14853))
|
||||||
|
- Glance: preserve glance.yml across updates [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14845](https://github.com/community-scripts/ProxmoxVE/pull/14845))
|
||||||
|
- NginxProxymanager: set Certbot version in npm.service environment variable (2.15.0) [@MickLesk](https://github.com/MickLesk) ([#14843](https://github.com/community-scripts/ProxmoxVE/pull/14843))
|
||||||
|
- [FileFlows] Fix service handling by using systemctl --all with quoted glob [@adrianmusante](https://github.com/adrianmusante) ([#14838](https://github.com/community-scripts/ProxmoxVE/pull/14838))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Kometa: also update Quickstart in update_script [@MickLesk](https://github.com/MickLesk) ([#14529](https://github.com/community-scripts/ProxmoxVE/pull/14529))
|
||||||
|
|
||||||
|
## 2026-05-31
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Manyfold: regenerate Rails credentials on update to fix encryption mimatch [@MickLesk](https://github.com/MickLesk) ([#14817](https://github.com/community-scripts/ProxmoxVE/pull/14817))
|
||||||
|
- OpenThread-BR: use correct ipv6 configuration [@tomfrenzel](https://github.com/tomfrenzel) ([#14829](https://github.com/community-scripts/ProxmoxVE/pull/14829))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Webtrees: use PHP CLI for initial setup instead of curl to setup wizard [@MickLesk](https://github.com/MickLesk) ([#14818](https://github.com/community-scripts/ProxmoxVE/pull/14818))
|
||||||
|
- Kima-Hub: use curl_with_retry for ML model downloads to fix possible timeout issues [@MickLesk](https://github.com/MickLesk) ([#14816](https://github.com/community-scripts/ProxmoxVE/pull/14816))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- PBS4-Upgrade: update current PBS3 packages before switching to Trixie repos [@MickLesk](https://github.com/MickLesk) ([#14815](https://github.com/community-scripts/ProxmoxVE/pull/14815))
|
||||||
|
|
||||||
|
## 2026-05-30
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Flatnotes: fix empty package name in pyproject.toml [@MickLesk](https://github.com/MickLesk) ([#14814](https://github.com/community-scripts/ProxmoxVE/pull/14814))
|
||||||
|
|
||||||
|
## 2026-05-29
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- Kan ([#14776](https://github.com/community-scripts/ProxmoxVE/pull/14776))
|
||||||
|
- Dynacat ([#14777](https://github.com/community-scripts/ProxmoxVE/pull/14777))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fix lobehub docker path [@dannyyy](https://github.com/dannyyy) ([#14793](https://github.com/community-scripts/ProxmoxVE/pull/14793))
|
||||||
|
- karakeep: add more hdd space [@MickLesk](https://github.com/MickLesk) ([#14797](https://github.com/community-scripts/ProxmoxVE/pull/14797))
|
||||||
|
- Grist: Revert installation of EE [@tremor021](https://github.com/tremor021) ([#14784](https://github.com/community-scripts/ProxmoxVE/pull/14784))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Sure: Remove `$STD` for `systemctl enable -q` [@tremor021](https://github.com/tremor021) ([#14801](https://github.com/community-scripts/ProxmoxVE/pull/14801))
|
||||||
|
|
||||||
|
## 2026-05-28
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- RomM: remove nginx default.conf during installation [@MickLesk](https://github.com/MickLesk) ([#14766](https://github.com/community-scripts/ProxmoxVE/pull/14766))
|
||||||
|
- Open-Archiver: replace pnpm approve-builds --yes with --all [@MickLesk](https://github.com/MickLesk) ([#14765](https://github.com/community-scripts/ProxmoxVE/pull/14765))
|
||||||
|
- fix(hermesagent): set npm_config_yes=true to suppress interactive pro… [@steveonjava](https://github.com/steveonjava) ([#14763](https://github.com/community-scripts/ProxmoxVE/pull/14763))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Yamtrack: migrate to uv [@MickLesk](https://github.com/MickLesk) ([#14767](https://github.com/community-scripts/ProxmoxVE/pull/14767))
|
||||||
|
|
||||||
|
### ❔ Uncategorized
|
||||||
|
|
||||||
|
- chore(ct): sync adventurelog defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#14772](https://github.com/community-scripts/ProxmoxVE/pull/14772))
|
||||||
|
|
||||||
|
## 2026-05-27
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- MusicSeerr ([#14746](https://github.com/community-scripts/ProxmoxVE/pull/14746))
|
||||||
|
- Hermes Agent ([#14751](https://github.com/community-scripts/ProxmoxVE/pull/14751))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- grist: restore install:ee step [@paulfitz](https://github.com/paulfitz) ([#14759](https://github.com/community-scripts/ProxmoxVE/pull/14759))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- [tools.func]: `setup_gs()` fix getting dotted release format [@tremor021](https://github.com/tremor021) ([#14745](https://github.com/community-scripts/ProxmoxVE/pull/14745))
|
||||||
|
|
||||||
|
## 2026-05-26
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Add directory creation to Profilarr update script [@ryansully](https://github.com/ryansully) ([#14740](https://github.com/community-scripts/ProxmoxVE/pull/14740))
|
||||||
|
- profilarr: Fix ARCH assignment in profilarr.sh to support Profilarr build usage [@mpeleshenko](https://github.com/mpeleshenko) ([#14709](https://github.com/community-scripts/ProxmoxVE/pull/14709))
|
||||||
|
- Jackett: Remove quotes in Service File [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#14729](https://github.com/community-scripts/ProxmoxVE/pull/14729))
|
||||||
|
- Open-archiver: approve pnpm build scripts and run build:oss without subshell [@MickLesk](https://github.com/MickLesk) ([#14711](https://github.com/community-scripts/ProxmoxVE/pull/14711))
|
||||||
|
- Docuseal: read Ruby version from Gemfile, upgrade on update if needed [@MickLesk](https://github.com/MickLesk) ([#14715](https://github.com/community-scripts/ProxmoxVE/pull/14715))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Birdnet-GO: install libonnxruntime.so from release tarball [@MickLesk](https://github.com/MickLesk) ([#14716](https://github.com/community-scripts/ProxmoxVE/pull/14716))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: better error diagnostics, consistent OS detection, setup function ordering [@MickLesk](https://github.com/MickLesk) ([#14692](https://github.com/community-scripts/ProxmoxVE/pull/14692))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- IPTag-Tool: use qm set for VM tags to handle snapshot sections crrectly [@MickLesk](https://github.com/MickLesk) ([#14713](https://github.com/community-scripts/ProxmoxVE/pull/14713))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Netdata: extend PVE version support to 9.x [@MickLesk](https://github.com/MickLesk) ([#14714](https://github.com/community-scripts/ProxmoxVE/pull/14714))
|
||||||
|
|
||||||
|
## 2026-05-25
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- karakeep: fix: pip config [@CrazyWolf13](https://github.com/CrazyWolf13) ([#14703](https://github.com/community-scripts/ProxmoxVE/pull/14703))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools.func: replace raw GitHub API curl calls with get_latest_github_release [@MickLesk](https://github.com/MickLesk) ([#14690](https://github.com/community-scripts/ProxmoxVE/pull/14690))
|
||||||
|
|
||||||
|
### 🧰 Tools
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Kernel-Clean: detect meta-packages and fix silent removal failures [@MickLesk](https://github.com/MickLesk) ([#14674](https://github.com/community-scripts/ProxmoxVE/pull/14674))
|
||||||
|
|
||||||
|
## 2026-05-24
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- RomM: add installation steps for Nginx mod_zip module [@MickLesk](https://github.com/MickLesk) ([#14678](https://github.com/community-scripts/ProxmoxVE/pull/14678))
|
||||||
|
- ISponsorblockTV: detect CPU capabilities to select compatible binary [@MickLesk](https://github.com/MickLesk) ([#14677](https://github.com/community-scripts/ProxmoxVE/pull/14677))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Refactor: MQTT [@tremor021](https://github.com/tremor021) ([#14673](https://github.com/community-scripts/ProxmoxVE/pull/14673))
|
||||||
|
|
||||||
## 2026-05-23
|
## 2026-05-23
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
@@ -897,298 +1098,3 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
- #### 🔧 Refactor
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
- Mail-Archiver: update dependencies [@tremor021](https://github.com/tremor021) ([#14152](https://github.com/community-scripts/ProxmoxVE/pull/14152))
|
- Mail-Archiver: update dependencies [@tremor021](https://github.com/tremor021) ([#14152](https://github.com/community-scripts/ProxmoxVE/pull/14152))
|
||||||
|
|
||||||
## 2026-04-30
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Nagios ([#14126](https://github.com/community-scripts/ProxmoxVE/pull/14126))
|
|
||||||
- Neko ([#14121](https://github.com/community-scripts/ProxmoxVE/pull/14121))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- alpine-docker: install openssl as core dependency | alpine-komodo: check & install openssl if missing [@MickLesk](https://github.com/MickLesk) ([#14134](https://github.com/community-scripts/ProxmoxVE/pull/14134))
|
|
||||||
- endurain: update source references to Codeberg [@MickLesk](https://github.com/MickLesk) ([#14128](https://github.com/community-scripts/ProxmoxVE/pull/14128))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- tools.func: Manage minor versions for MongoDB 8.x [@tremor021](https://github.com/tremor021) ([#14131](https://github.com/community-scripts/ProxmoxVE/pull/14131))
|
|
||||||
|
|
||||||
## 2026-04-29
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- GrayLog: MongoDB update to 8.2.x [@tremor021](https://github.com/tremor021) ([#14114](https://github.com/community-scripts/ProxmoxVE/pull/14114))
|
|
||||||
- Graylog: Better information in the log file [@tremor021](https://github.com/tremor021) ([#14110](https://github.com/community-scripts/ProxmoxVE/pull/14110))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Refactor: checkMK [@MickLesk](https://github.com/MickLesk) ([#14105](https://github.com/community-scripts/ProxmoxVE/pull/14105))
|
|
||||||
- PatchMon: Unpin release [@tremor021](https://github.com/tremor021) ([#14097](https://github.com/community-scripts/ProxmoxVE/pull/14097))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- core: add guidance when storage lacks rootdir support [@MickLesk](https://github.com/MickLesk) ([#14108](https://github.com/community-scripts/ProxmoxVE/pull/14108))
|
|
||||||
|
|
||||||
## 2026-04-28
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- StoryBook ([#14081](https://github.com/community-scripts/ProxmoxVE/pull/14081))
|
|
||||||
- CoreDNS ([#14082](https://github.com/community-scripts/ProxmoxVE/pull/14082))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- Fix Dawarich Install/Update [@Jerry1098](https://github.com/Jerry1098) ([#14078](https://github.com/community-scripts/ProxmoxVE/pull/14078))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- PatchMon Version 2.0.2 Script update [@9technologygroup](https://github.com/9technologygroup) ([#14095](https://github.com/community-scripts/ProxmoxVE/pull/14095))
|
|
||||||
|
|
||||||
## 2026-04-27
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- Add pamUsername column to userOrgs table [@JVKeller](https://github.com/JVKeller) ([#14075](https://github.com/community-scripts/ProxmoxVE/pull/14075))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Dawarich: run db:migrate before assets:precompile [@MickLesk](https://github.com/MickLesk) ([#14051](https://github.com/community-scripts/ProxmoxVE/pull/14051))
|
|
||||||
- TechnitiumDNS: always install .NET 10 if not already present [@MickLesk](https://github.com/MickLesk) ([#14049](https://github.com/community-scripts/ProxmoxVE/pull/14049))
|
|
||||||
|
|
||||||
- #### 💥 Breaking Changes
|
|
||||||
|
|
||||||
- PatchMon: v2.0.0 migration [@vhsdream](https://github.com/vhsdream) ([#14015](https://github.com/community-scripts/ProxmoxVE/pull/14015))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Update build.func - fixed spelling mistake [@m1ckywill](https://github.com/m1ckywill) ([#14047](https://github.com/community-scripts/ProxmoxVE/pull/14047))
|
|
||||||
|
|
||||||
### 🧰 Tools
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- update-lxcs/apps: avoid pct exec on containers mid-shutdown [@MickLesk](https://github.com/MickLesk) ([#14050](https://github.com/community-scripts/ProxmoxVE/pull/14050))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Add patchmon-agent report execution in update script [@heinemannj](https://github.com/heinemannj) ([#14054](https://github.com/community-scripts/ProxmoxVE/pull/14054))
|
|
||||||
|
|
||||||
## 2026-04-26
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- TREK ([#14017](https://github.com/community-scripts/ProxmoxVE/pull/14017))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- fix(2fauth): handle stale backup directory on update [@omertahaoztop](https://github.com/omertahaoztop) ([#14018](https://github.com/community-scripts/ProxmoxVE/pull/14018))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Increase Frigate default CPU cores from 4 to 8 [@MickLesk](https://github.com/MickLesk) ([#14039](https://github.com/community-scripts/ProxmoxVE/pull/14039))
|
|
||||||
- Technitium DNS: Ensure directories exist before running service [@tremor021](https://github.com/tremor021) ([#14030](https://github.com/community-scripts/ProxmoxVE/pull/14030))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: Correct deb822 repository flat path detection [@MickLesk](https://github.com/MickLesk) ([#14037](https://github.com/community-scripts/ProxmoxVE/pull/14037))
|
|
||||||
|
|
||||||
## 2026-04-25
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- VictoriaMetrics: Stop vmagent/vmalert before update [@irishpadres](https://github.com/irishpadres) ([#14016](https://github.com/community-scripts/ProxmoxVE/pull/14016))
|
|
||||||
- Domain-Monitor: start apache2 after stop instead of reload [@omertahaoztop](https://github.com/omertahaoztop) ([#14019](https://github.com/community-scripts/ProxmoxVE/pull/14019))
|
|
||||||
- Transmute: Fix ffmpeg detection [@tremor021](https://github.com/tremor021) ([#14008](https://github.com/community-scripts/ProxmoxVE/pull/14008))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Refactor: Technitium DNS [@tremor021](https://github.com/tremor021) ([#14013](https://github.com/community-scripts/ProxmoxVE/pull/14013))
|
|
||||||
|
|
||||||
## 2026-04-24
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Apprise-API ([#13934](https://github.com/community-scripts/ProxmoxVE/pull/13934))
|
|
||||||
- fireshare ([#13995](https://github.com/community-scripts/ProxmoxVE/pull/13995))
|
|
||||||
- Transmute ([#13935](https://github.com/community-scripts/ProxmoxVE/pull/13935))
|
|
||||||
- Jitsi-Meet ([#13897](https://github.com/community-scripts/ProxmoxVE/pull/13897))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- Update wger.sh [@Soppster1029](https://github.com/Soppster1029) ([#13977](https://github.com/community-scripts/ProxmoxVE/pull/13977))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Refactor: Ghostfolio [@MickLesk](https://github.com/MickLesk) ([#13990](https://github.com/community-scripts/ProxmoxVE/pull/13990))
|
|
||||||
|
|
||||||
## 2026-04-23
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- mealie: start.sh missing after failed update [@MickLesk](https://github.com/MickLesk) ([#13958](https://github.com/community-scripts/ProxmoxVE/pull/13958))
|
|
||||||
- twingate-connector: perform real apt upgrade during update flow [@MickLesk](https://github.com/MickLesk) ([#13959](https://github.com/community-scripts/ProxmoxVE/pull/13959))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- core: auto-size NODE_OPTIONS heap [@MickLesk](https://github.com/MickLesk) ([#13960](https://github.com/community-scripts/ProxmoxVE/pull/13960))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Update scripts to match standard [@tremor021](https://github.com/tremor021) ([#13956](https://github.com/community-scripts/ProxmoxVE/pull/13956))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- tools.func: upgrade Node.js minor/patch on same major version [@MickLesk](https://github.com/MickLesk) ([#13957](https://github.com/community-scripts/ProxmoxVE/pull/13957))
|
|
||||||
- core: hotfix - prefer silent mode on PHS env conflict [@MickLesk](https://github.com/MickLesk) ([#13951](https://github.com/community-scripts/ProxmoxVE/pull/13951))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- core: improve system update information / lxc stack upgrade [@MickLesk](https://github.com/MickLesk) ([#13970](https://github.com/community-scripts/ProxmoxVE/pull/13970))
|
|
||||||
|
|
||||||
## 2026-04-22
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Dashy ([#13817](https://github.com/community-scripts/ProxmoxVE/pull/13817))
|
|
||||||
- Mini-QR ([#13902](https://github.com/community-scripts/ProxmoxVE/pull/13902))
|
|
||||||
- ownfoil ([#13904](https://github.com/community-scripts/ProxmoxVE/pull/13904))
|
|
||||||
- ERPNext ([#13921](https://github.com/community-scripts/ProxmoxVE/pull/13921))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- add --clear to uv venv in update_script() to prevent interactive prompt [@MickLesk](https://github.com/MickLesk) ([#13926](https://github.com/community-scripts/ProxmoxVE/pull/13926))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- core: Add PHS_VERBOSE env var to skip verbose mode prompts [@gormanity](https://github.com/gormanity) ([#13797](https://github.com/community-scripts/ProxmoxVE/pull/13797))
|
|
||||||
|
|
||||||
## 2026-04-21
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- gogs ([#13896](https://github.com/community-scripts/ProxmoxVE/pull/13896))
|
|
||||||
- anchor ([#13895](https://github.com/community-scripts/ProxmoxVE/pull/13895))
|
|
||||||
- minthcm ([#13903](https://github.com/community-scripts/ProxmoxVE/pull/13903))
|
|
||||||
- foldergram ([#13900](https://github.com/community-scripts/ProxmoxVE/pull/13900))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- OpenCloud: Pin version to 6.1.0 [@vhsdream](https://github.com/vhsdream) ([#13890](https://github.com/community-scripts/ProxmoxVE/pull/13890))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Domain-Locker: Update dependencies [@tremor021](https://github.com/tremor021) ([#13901](https://github.com/community-scripts/ProxmoxVE/pull/13901))
|
|
||||||
- homelable: fix install failure by correcting password-reset chmod target [@Copilot](https://github.com/Copilot) ([#13894](https://github.com/community-scripts/ProxmoxVE/pull/13894))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- FileFlows: Update dependencies [@tremor021](https://github.com/tremor021) ([#13917](https://github.com/community-scripts/ProxmoxVE/pull/13917))
|
|
||||||
|
|
||||||
## 2026-04-20
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- WhoDB ([#13880](https://github.com/community-scripts/ProxmoxVE/pull/13880))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- pangolin: create migration tables before data transfer to prevent role loss [@MickLesk](https://github.com/MickLesk) ([#13874](https://github.com/community-scripts/ProxmoxVE/pull/13874))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Pangolin: pre-apply schema migrations to prevent data loss [@MickLesk](https://github.com/MickLesk) ([#13861](https://github.com/community-scripts/ProxmoxVE/pull/13861))
|
|
||||||
- ActualBudget: change migration messages to warnings [@MickLesk](https://github.com/MickLesk) ([#13860](https://github.com/community-scripts/ProxmoxVE/pull/13860))
|
|
||||||
- slskd: migrate config keys for 0.25.0 breaking change [@MickLesk](https://github.com/MickLesk) ([#13862](https://github.com/community-scripts/ProxmoxVE/pull/13862))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Wanderer: add pocketbase CLI wrapper with env [@MickLesk](https://github.com/MickLesk) ([#13863](https://github.com/community-scripts/ProxmoxVE/pull/13863))
|
|
||||||
- feat(homelable): add password reset utility script [@davidsoncabista](https://github.com/davidsoncabista) ([#13798](https://github.com/community-scripts/ProxmoxVE/pull/13798))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Several Scripts: Bump NodeJS to align Node.js versions with upstream for 5 scripts [@MickLesk](https://github.com/MickLesk) ([#13875](https://github.com/community-scripts/ProxmoxVE/pull/13875))
|
|
||||||
- Refactor: PMG Post Install [@MickLesk](https://github.com/MickLesk) ([#13693](https://github.com/community-scripts/ProxmoxVE/pull/13693))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: detect Perl breakage after LXC stack upgrade and improve storage validation [@MickLesk](https://github.com/MickLesk) ([#13879](https://github.com/community-scripts/ProxmoxVE/pull/13879))
|
|
||||||
|
|
||||||
## 2026-04-19
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- nametag ([#13849](https://github.com/community-scripts/ProxmoxVE/pull/13849))
|
|
||||||
|
|
||||||
## 2026-04-18
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Dagu ([#13830](https://github.com/community-scripts/ProxmoxVE/pull/13830))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- BabyBuddy: set DJANGO_SETTINGS_MODULE before migrate in update [@MickLesk](https://github.com/MickLesk) ([#13836](https://github.com/community-scripts/ProxmoxVE/pull/13836))
|
|
||||||
- litellm: add prisma generate and use venv binary directly [@MickLesk](https://github.com/MickLesk) ([#13835](https://github.com/community-scripts/ProxmoxVE/pull/13835))
|
|
||||||
- yamtrack: add missing nginx.conf sed edits to update script [@MickLesk](https://github.com/MickLesk) ([#13834](https://github.com/community-scripts/ProxmoxVE/pull/13834))
|
|
||||||
|
|
||||||
### 🧰 Tools
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- SparkyFitness Garmin Microservice: fix update function [@tomfrenzel](https://github.com/tomfrenzel) ([#13824](https://github.com/community-scripts/ProxmoxVE/pull/13824))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Clean-Orphan-LVM: check all cluster nodes for VM/CT configs [@MickLesk](https://github.com/MickLesk) ([#13837](https://github.com/community-scripts/ProxmoxVE/pull/13837))
|
|
||||||
|
|
||||||
## 2026-04-17
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- step-ca ([#13775](https://github.com/community-scripts/ProxmoxVE/pull/13775))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: pin IGC version to compute-runtime compatible tag (Intel GPU) [@MickLesk](https://github.com/MickLesk) ([#13814](https://github.com/community-scripts/ProxmoxVE/pull/13814))
|
|
||||||
- Fix for bambuddy community script update [@abbasegbeyemi](https://github.com/abbasegbeyemi) ([#13816](https://github.com/community-scripts/ProxmoxVE/pull/13816))
|
|
||||||
- Umami: Fix update procedure [@tremor021](https://github.com/tremor021) ([#13807](https://github.com/community-scripts/ProxmoxVE/pull/13807))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: sanitize mount_fs input — strip spaces and trailing commas [@MickLesk](https://github.com/MickLesk) ([#13806](https://github.com/community-scripts/ProxmoxVE/pull/13806))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- core: fix some pct create issues (telemetry) + cleanup [@MickLesk](https://github.com/MickLesk) ([#13810](https://github.com/community-scripts/ProxmoxVE/pull/13810))
|
|
||||||
@@ -9,7 +9,7 @@ APP="AdventureLog"
|
|||||||
var_tags="${var_tags:-traveling}"
|
var_tags="${var_tags:-traveling}"
|
||||||
var_disk="${var_disk:-7}"
|
var_disk="${var_disk:-7}"
|
||||||
var_cpu="${var_cpu:-2}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-2048}"
|
var_ram="${var_ram:-4096}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_arm64="${var_arm64:-no}"
|
var_arm64="${var_arm64:-no}"
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ function update_script() {
|
|||||||
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
|
cp /opt/birdnet/birdnet-go /usr/local/bin/birdnet-go
|
||||||
chmod +x /usr/local/bin/birdnet-go
|
chmod +x /usr/local/bin/birdnet-go
|
||||||
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
|
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
|
||||||
|
cp -r /opt/birdnet/libonnxruntime.so /usr/local/lib/ || true
|
||||||
ldconfig
|
ldconfig
|
||||||
msg_ok "Deployed Binary"
|
msg_ok "Deployed Binary"
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function update_script() {
|
|||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
|
|
||||||
NODE_VERSION="24" setup_nodejs
|
NODE_VERSION="26" setup_nodejs
|
||||||
ensure_dependencies build-essential
|
ensure_dependencies build-essential
|
||||||
|
|
||||||
if command -v cross-seed &>/dev/null; then
|
if command -v cross-seed &>/dev/null; then
|
||||||
|
|||||||
10
ct/degoog.sh
10
ct/degoog.sh
@@ -49,11 +49,21 @@ function update_script() {
|
|||||||
msg_ok "Installed Bun"
|
msg_ok "Installed Bun"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
msg_info "Updating Valkey"
|
||||||
|
ensure_dependencies valkey
|
||||||
|
msg_ok "Updated Valkey"
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
|
||||||
|
|
||||||
msg_info "Restoring Configuration & Data"
|
msg_info "Restoring Configuration & Data"
|
||||||
[[ -f /opt/degoog.env.bak ]] && mv /opt/degoog.env.bak /opt/degoog/.env
|
[[ -f /opt/degoog.env.bak ]] && mv /opt/degoog.env.bak /opt/degoog/.env
|
||||||
[[ -d /opt/degoog_data_backup ]] && mv /opt/degoog_data_backup /opt/degoog/data
|
[[ -d /opt/degoog_data_backup ]] && mv /opt/degoog_data_backup /opt/degoog/data
|
||||||
|
|
||||||
|
if [[ -f /opt/degoog/.env ]]; then
|
||||||
|
grep -q "^DEGOOG_VALKEY_URL=" /opt/degoog/.env && sed -i "s|^DEGOOG_VALKEY_URL=.*|DEGOOG_VALKEY_URL=redis://valkey:6379|" /opt/degoog/.env || echo "DEGOOG_VALKEY_URL=redis://valkey:6379" >>/opt/degoog/.env
|
||||||
|
grep -q "^DEGOOG_CACHE_MAX_ENTRIES=" /opt/degoog/.env && sed -i "s|^DEGOOG_CACHE_MAX_ENTRIES=.*|DEGOOG_CACHE_MAX_ENTRIES=1000|" /opt/degoog/.env || echo "DEGOOG_CACHE_MAX_ENTRIES=1000" >>/opt/degoog/.env
|
||||||
|
grep -q "^DEGOOG_CACHE_TTL_MS=" /opt/degoog/.env && sed -i "s|^DEGOOG_CACHE_TTL_MS=.*|DEGOOG_CACHE_TTL_MS=43200000|" /opt/degoog/.env || echo "DEGOOG_CACHE_TTL_MS=43200000" >>/opt/degoog/.env
|
||||||
|
fi
|
||||||
msg_ok "Restored Configuration & Data"
|
msg_ok "Restored Configuration & Data"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ function update_script() {
|
|||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "docuseal" "docusealco/docuseal" "tarball"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "docuseal" "docusealco/docuseal" "tarball"
|
||||||
|
|
||||||
|
local required_ruby current_ruby
|
||||||
|
required_ruby=$(grep -m1 '^ruby ' /opt/docuseal/Gemfile | grep -oP '[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
|
current_ruby=$(PATH="/root/.rbenv/bin:/root/.rbenv/shims:${PATH}" rbenv global 2>/dev/null || true)
|
||||||
|
if [[ -n "$required_ruby" && "$required_ruby" != "$current_ruby" ]]; then
|
||||||
|
RUBY_VERSION="${required_ruby}" RUBY_INSTALL_RAILS="false" HOME=/root setup_ruby
|
||||||
|
fi
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
mv /opt/docuseal.env.bak /opt/docuseal/.env
|
mv /opt/docuseal.env.bak /opt/docuseal/.env
|
||||||
[[ -d /opt/docuseal_data.bak ]] && mv /opt/docuseal_data.bak /opt/docuseal/data
|
[[ -d /opt/docuseal_data.bak ]] && mv /opt/docuseal_data.bak /opt/docuseal/data
|
||||||
|
|||||||
69
ct/dynacat.sh
Normal file
69
ct/dynacat.sh
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/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/Panonim/dynacat
|
||||||
|
|
||||||
|
APP="Dynacat"
|
||||||
|
var_tags="${var_tags:-dashboard;homepage;monitoring}"
|
||||||
|
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:-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 [[ ! -f /opt/dynacat/dynacat ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "dynacat" "Panonim/dynacat"; then
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop dynacat
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Backing up Data"
|
||||||
|
cp -r /opt/dynacat/config /opt/dynacat_config_backup
|
||||||
|
cp -r /opt/dynacat/assets /opt/dynacat_assets_backup
|
||||||
|
cp -r /opt/dynacat/data /opt/dynacat_data_backup
|
||||||
|
msg_ok "Backed up Data"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "dynacat" "Panonim/dynacat" "prebuild" "latest" "/opt/dynacat" "dynacat-linux-amd64.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Restoring Data"
|
||||||
|
cp -r /opt/dynacat_config_backup/. /opt/dynacat/config
|
||||||
|
cp -r /opt/dynacat_assets_backup/. /opt/dynacat/assets
|
||||||
|
cp -r /opt/dynacat_data_backup/. /opt/dynacat/data
|
||||||
|
rm -rf /opt/dynacat_config_backup /opt/dynacat_assets_backup /opt/dynacat_data_backup
|
||||||
|
chmod +x /opt/dynacat/dynacat
|
||||||
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start dynacat
|
||||||
|
msg_ok "Started Service"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
|
||||||
@@ -34,7 +34,7 @@ function update_script() {
|
|||||||
update_available=$(curl -fsSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable)
|
update_available=$(curl -fsSL -X 'GET' "http://localhost:19200/api/status/update-available" -H 'accept: application/json' | jq .UpdateAvailable)
|
||||||
if [[ "${update_available}" == "true" ]]; then
|
if [[ "${update_available}" == "true" ]]; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop fileflows*
|
systemctl --all stop 'fileflows*'
|
||||||
msg_info "Stopped Service"
|
msg_info "Stopped Service"
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
msg_info "Creating Backup"
|
||||||
@@ -46,7 +46,7 @@ function update_script() {
|
|||||||
fetch_and_deploy_from_url "https://fileflows.com/downloads/zip" "/opt/fileflows"
|
fetch_and_deploy_from_url "https://fileflows.com/downloads/zip" "/opt/fileflows"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start fileflows*
|
systemctl --all start 'fileflows*'
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ function update_script() {
|
|||||||
export VIDEO_DIRECTORY=/opt/fireshare-videos
|
export VIDEO_DIRECTORY=/opt/fireshare-videos
|
||||||
export PROCESSED_DIRECTORY=/opt/fireshare-processed
|
export PROCESSED_DIRECTORY=/opt/fireshare-processed
|
||||||
$STD uv run flask db upgrade
|
$STD uv run flask db upgrade
|
||||||
|
|
||||||
|
msg_info "Building Fireshare Client"
|
||||||
|
cd /opt/fireshare/app/client
|
||||||
|
$STD npm install
|
||||||
|
$STD npm run build
|
||||||
|
msg_ok "Built Fireshare Client"
|
||||||
msg_ok "Updated Fireshare"
|
msg_ok "Updated Fireshare"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ function update_script() {
|
|||||||
$STD npm run build
|
$STD npm run build
|
||||||
cd /opt/flatnotes
|
cd /opt/flatnotes
|
||||||
rm -f uv.lock
|
rm -f uv.lock
|
||||||
|
sed -i 's/^name = ""$/name = "flatnotes"/' pyproject.toml
|
||||||
$STD /usr/local/bin/uvx migrate-to-uv
|
$STD /usr/local/bin/uvx migrate-to-uv
|
||||||
$STD /usr/local/bin/uv sync
|
$STD /usr/local/bin/uv sync
|
||||||
msg_ok "Updated Flatnotes"
|
msg_ok "Updated Flatnotes"
|
||||||
|
|||||||
12
ct/glance.sh
12
ct/glance.sh
@@ -34,8 +34,20 @@ function update_script() {
|
|||||||
systemctl stop glance
|
systemctl stop glance
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
if [[ -f /opt/glance/glance.yml ]]; then
|
||||||
|
msg_info "Backing up glance.yml"
|
||||||
|
cp /opt/glance/glance.yml /tmp/glance.yml.bak
|
||||||
|
msg_ok "Backed up glance.yml"
|
||||||
|
fi
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "glance" "glanceapp/glance" "prebuild" "latest" "/opt/glance" "glance-linux-amd64.tar.gz"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "glance" "glanceapp/glance" "prebuild" "latest" "/opt/glance" "glance-linux-amd64.tar.gz"
|
||||||
|
|
||||||
|
if [[ -f /tmp/glance.yml.bak ]]; then
|
||||||
|
msg_info "Restoring glance.yml"
|
||||||
|
mv /tmp/glance.yml.bak /opt/glance/glance.yml
|
||||||
|
msg_ok "Restored glance.yml"
|
||||||
|
fi
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start glance
|
systemctl start glance
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|||||||
6
ct/headers/dynacat
Normal file
6
ct/headers/dynacat
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
____ __
|
||||||
|
/ __ \__ ______ ____ __________ _/ /_
|
||||||
|
/ / / / / / / __ \/ __ `/ ___/ __ `/ __/
|
||||||
|
/ /_/ / /_/ / / / / /_/ / /__/ /_/ / /_
|
||||||
|
/_____/\__, /_/ /_/\__,_/\___/\__,_/\__/
|
||||||
|
/____/
|
||||||
6
ct/headers/hermesagent
Normal file
6
ct/headers/hermesagent
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ __ ___ __
|
||||||
|
/ / / /__ _________ ___ ___ _____ / | ____ ____ ____ / /_
|
||||||
|
/ /_/ / _ \/ ___/ __ `__ \/ _ \/ ___/ / /| |/ __ `/ _ \/ __ \/ __/
|
||||||
|
/ __ / __/ / / / / / / / __(__ ) / ___ / /_/ / __/ / / / /_
|
||||||
|
/_/ /_/\___/_/ /_/ /_/ /_/\___/____/ /_/ |_\__, /\___/_/ /_/\__/
|
||||||
|
/____/
|
||||||
6
ct/headers/kan
Normal file
6
ct/headers/kan
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ __
|
||||||
|
/ //_/___ _____
|
||||||
|
/ ,< / __ `/ __ \
|
||||||
|
/ /| / /_/ / / / /
|
||||||
|
/_/ |_\__,_/_/ /_/
|
||||||
|
|
||||||
6
ct/headers/musicseerr
Normal file
6
ct/headers/musicseerr
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ ___ _ _____
|
||||||
|
/ |/ /_ _______(_)____/ ___/___ ___ __________
|
||||||
|
/ /|_/ / / / / ___/ / ___/\__ \/ _ \/ _ \/ ___/ ___/
|
||||||
|
/ / / / /_/ (__ ) / /__ ___/ / __/ __/ / / /
|
||||||
|
/_/ /_/\__,_/____/_/\___//____/\___/\___/_/ /_/
|
||||||
|
|
||||||
73
ct/hermesagent.sh
Normal file
73
ct/hermesagent.sh
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#!/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: Stephen Chin (steveonjava)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://hermes-agent.nousresearch.com/
|
||||||
|
|
||||||
|
APP="Hermes Agent"
|
||||||
|
var_tags="${var_tags:-ai;automation;agent}"
|
||||||
|
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}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -x /home/hermes/.local/bin/hermes ]]; then
|
||||||
|
msg_error "No Hermes Agent Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_warn "WARNING: This script will run an external installer from a third-party source (https://hermes-agent.nousresearch.com/)."
|
||||||
|
msg_warn "The following code is NOT maintained or audited by our repository."
|
||||||
|
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
|
||||||
|
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ hermes update (https://hermes-agent.nousresearch.com/)"
|
||||||
|
echo
|
||||||
|
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
|
||||||
|
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||||
|
msg_error "Aborted by user. No changes have been made."
|
||||||
|
exit 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop hermes-dashboard
|
||||||
|
msg_ok "Stopped Services"
|
||||||
|
|
||||||
|
msg_info "Updating Hermes Agent"
|
||||||
|
$STD setsid --wait bash -c '
|
||||||
|
set -a; source /etc/default/hermes; set +a
|
||||||
|
/home/hermes/.local/bin/hermes update --yes
|
||||||
|
'
|
||||||
|
chown -R hermes:hermes /home/hermes
|
||||||
|
msg_ok "Updated Hermes Agent"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
systemctl start hermes-dashboard
|
||||||
|
msg_ok "Started Services"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}Hermes Agent setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Configure your model provider and gateway server inside the container:${CL}"
|
||||||
|
echo -e "${TAB}${BGN}hermes-setup${CL}"
|
||||||
|
echo -e "${INFO} When prompted to install the gateway service, choose 'user service'.${CL}"
|
||||||
|
echo -e "${INFO}${YW} Key for Hermes API Server stored in:${CL}"
|
||||||
|
echo -e "${TAB}${BGN}/home/hermes/.hermes/.env${CL}"
|
||||||
@@ -35,7 +35,7 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Creating backup"
|
msg_info "Creating backup"
|
||||||
[[ -f /opt/infisical_backup.sql ]] && rm -f /opt/infisical_backup.sql
|
[[ -f /opt/infisical_backup.sql ]] && rm -f /opt/infisical_backup.sql
|
||||||
DB_PASS=$(grep -Po '(?<=^Database Password:\s).*' ~/infisical.creds | head -n1)
|
DB_PASS=$(grep -Po '(?<=^Password:\s).*' ~/infisical.creds | head -n1)
|
||||||
PGPASSWORD=$DB_PASS pg_dump -U infisical -h localhost -d infisical_db > /opt/infisical_backup.sql
|
PGPASSWORD=$DB_PASS pg_dump -U infisical -h localhost -d infisical_db > /opt/infisical_backup.sql
|
||||||
msg_ok "Created backup"
|
msg_ok "Created backup"
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,11 @@ function update_script() {
|
|||||||
systemctl stop isponsorblocktv
|
systemctl stop isponsorblocktv
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "iSponsorBlockTV-x86_64-linux"
|
ISBTV_BINARY="iSponsorBlockTV-x86_64-linux-v1"
|
||||||
|
if grep -q ' avx ' /proc/cpuinfo 2>/dev/null && grep -q ' avx2 ' /proc/cpuinfo 2>/dev/null && grep -q ' movbe ' /proc/cpuinfo 2>/dev/null; then
|
||||||
|
ISBTV_BINARY="iSponsorBlockTV-x86_64-linux"
|
||||||
|
fi
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "${ISBTV_BINARY}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start isponsorblocktv
|
systemctl start isponsorblocktv
|
||||||
|
|||||||
86
ct/kan.sh
Normal file
86
ct/kan.sh
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/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/kanbn/kan
|
||||||
|
|
||||||
|
APP="Kan"
|
||||||
|
var_tags="${var_tags:-project-management;kanban}"
|
||||||
|
var_cpu="${var_cpu:-4}"
|
||||||
|
var_ram="${var_ram:-4096}"
|
||||||
|
var_disk="${var_disk:-12}"
|
||||||
|
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/kan ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_tag "kan" "kanbn/kan"; then
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop kan
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Backing up Data"
|
||||||
|
cp /opt/kan/.env /opt/kan.env.bak
|
||||||
|
msg_ok "Backed up Data"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_tag "kan" "kanbn/kan" "latest"
|
||||||
|
|
||||||
|
msg_info "Restoring Configuration"
|
||||||
|
cp /opt/kan.env.bak /opt/kan/.env
|
||||||
|
rm -f /opt/kan.env.bak
|
||||||
|
msg_ok "Restored Configuration"
|
||||||
|
|
||||||
|
msg_info "Building Application"
|
||||||
|
cd /opt/kan
|
||||||
|
set -a && source /opt/kan/.env && set +a
|
||||||
|
export NEXT_PUBLIC_USE_STANDALONE_OUTPUT=true
|
||||||
|
$STD pnpm install --ignore-scripts --prod=false
|
||||||
|
export CI=true
|
||||||
|
find /opt/kan/packages /opt/kan/apps -name 'tsconfig.json' -exec sed -i 's|"@kan/tsconfig/|"../../tooling/typescript/|g' {} +
|
||||||
|
$STD pnpm build --filter=@kan/web
|
||||||
|
unset NEXT_PUBLIC_USE_STANDALONE_OUTPUT CI
|
||||||
|
msg_ok "Built Application"
|
||||||
|
|
||||||
|
msg_info "Setting up Standalone"
|
||||||
|
mkdir -p /opt/kan/apps/web/.next/standalone/apps/web/.next/static
|
||||||
|
cp -r /opt/kan/apps/web/.next/static/* /opt/kan/apps/web/.next/standalone/apps/web/.next/static/
|
||||||
|
cp -r /opt/kan/apps/web/public /opt/kan/apps/web/.next/standalone/apps/web/public
|
||||||
|
msg_ok "Set up Standalone"
|
||||||
|
|
||||||
|
msg_info "Running Database Migrations"
|
||||||
|
cd /opt/kan/packages/db
|
||||||
|
$STD pnpm exec drizzle-kit migrate
|
||||||
|
msg_ok "Ran Database Migrations"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start kan
|
||||||
|
msg_ok "Started Service"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
|
||||||
@@ -9,7 +9,7 @@ APP="karakeep"
|
|||||||
var_tags="${var_tags:-bookmark}"
|
var_tags="${var_tags:-bookmark}"
|
||||||
var_cpu="${var_cpu:-2}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-4096}"
|
var_ram="${var_ram:-4096}"
|
||||||
var_disk="${var_disk:-10}"
|
var_disk="${var_disk:-15}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_arm64="${var_arm64:-no}"
|
var_arm64="${var_arm64:-no}"
|
||||||
@@ -46,6 +46,14 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
msg_ok "Update prepared"
|
msg_ok "Update prepared"
|
||||||
|
|
||||||
|
if [ ! -f ~/.config/pip/pip.conf ]; then
|
||||||
|
mkdir -p ~/.config/pip
|
||||||
|
cat <<EOF >~/.config/pip/pip.conf
|
||||||
|
[global]
|
||||||
|
break-system-packages = true
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
if grep -q "start:prod" /etc/systemd/system/karakeep-workers.service; then
|
if grep -q "start:prod" /etc/systemd/system/karakeep-workers.service; then
|
||||||
sed -i 's|^ExecStart=.*$|ExecStart=/usr/bin/node dist/index.mjs|' /etc/systemd/system/karakeep-workers.service
|
sed -i 's|^ExecStart=.*$|ExecStart=/usr/bin/node dist/index.mjs|' /etc/systemd/system/karakeep-workers.service
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ function update_script() {
|
|||||||
[[ -s /opt/koillection/.env.local && -n "$(tail -c 1 /opt/koillection/.env.local)" ]] && echo "" >>/opt/koillection/.env.local
|
[[ -s /opt/koillection/.env.local && -n "$(tail -c 1 /opt/koillection/.env.local)" ]] && echo "" >>/opt/koillection/.env.local
|
||||||
echo 'APP_RUNTIME="Symfony\Component\Runtime\SymfonyRuntime"' >>/opt/koillection/.env.local
|
echo 'APP_RUNTIME="Symfony\Component\Runtime\SymfonyRuntime"' >>/opt/koillection/.env.local
|
||||||
fi
|
fi
|
||||||
|
NODE_VERSION="26" NODE_MODULE="yarn" setup_nodejs
|
||||||
export COMPOSER_ALLOW_SUPERUSER=1
|
export COMPOSER_ALLOW_SUPERUSER=1
|
||||||
export APP_RUNTIME='Symfony\Component\Runtime\SymfonyRuntime'
|
export APP_RUNTIME='Symfony\Component\Runtime\SymfonyRuntime'
|
||||||
$STD composer install --no-dev -o --no-interaction --classmap-authoritative
|
$STD composer install --no-dev -o --no-interaction --classmap-authoritative
|
||||||
|
|||||||
20
ct/kometa.sh
20
ct/kometa.sh
@@ -32,6 +32,7 @@ function update_script() {
|
|||||||
if check_for_gh_release "kometa" "Kometa-Team/Kometa"; then
|
if check_for_gh_release "kometa" "Kometa-Team/Kometa"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop kometa
|
systemctl stop kometa
|
||||||
|
[[ -d "/opt/kometa-quickstart" ]] && systemctl stop kometa-quickstart
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Backing up data"
|
msg_info "Backing up data"
|
||||||
@@ -50,9 +51,28 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start kometa
|
systemctl start kometa
|
||||||
|
[[ -d "/opt/kometa-quickstart" ]] && systemctl start kometa-quickstart
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -d "/opt/kometa-quickstart" ]] && check_for_gh_release "kometa-quickstart" "Kometa-Team/Quickstart"; then
|
||||||
|
msg_info "Stopping Quickstart Service"
|
||||||
|
systemctl stop kometa-quickstart
|
||||||
|
msg_ok "Stopped Quickstart Service"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "kometa-quickstart" "Kometa-Team/Quickstart" "tarball"
|
||||||
|
|
||||||
|
msg_info "Updating Kometa Quickstart"
|
||||||
|
cd /opt/kometa-quickstart
|
||||||
|
$STD uv pip install -r requirements.txt -p /opt/kometa-quickstart/.venv/bin/python
|
||||||
|
msg_ok "Updated Kometa Quickstart"
|
||||||
|
|
||||||
|
msg_info "Starting Quickstart Service"
|
||||||
|
systemctl start kometa-quickstart
|
||||||
|
msg_ok "Started Quickstart Service"
|
||||||
|
msg_ok "Updated Quickstart successfully!"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ function update_script() {
|
|||||||
unset NODE_OPTIONS
|
unset NODE_OPTIONS
|
||||||
msg_ok "Built Application"
|
msg_ok "Built Application"
|
||||||
|
|
||||||
|
msg_info "Setting Up Standalone"
|
||||||
|
cp -r /opt/lobehub/.next/static /opt/lobehub/.next/standalone/.next/static
|
||||||
|
cp -r /opt/lobehub/public /opt/lobehub/.next/standalone/public
|
||||||
|
cp -r /opt/lobehub/scripts/migrateServerDB/* /opt/lobehub/.next/standalone/
|
||||||
|
cp -r /opt/lobehub/packages/database/migrations /opt/lobehub/.next/standalone/migrations
|
||||||
|
msg_ok "Set Up Standalone"
|
||||||
|
|
||||||
msg_info "Running Database Migrations"
|
msg_info "Running Database Migrations"
|
||||||
cd /opt/lobehub
|
cd /opt/lobehub
|
||||||
set -a && source /opt/lobehub/.env && set +a
|
set -a && source /opt/lobehub/.env && set +a
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ function update_script() {
|
|||||||
CURRENT_VERSION=$(grep -oP 'APP_VERSION=\K[^ ]+' /opt/manyfold/.env || echo "unknown")
|
CURRENT_VERSION=$(grep -oP 'APP_VERSION=\K[^ ]+' /opt/manyfold/.env || echo "unknown")
|
||||||
cp -r /opt/manyfold/app/storage /opt/manyfold_storage_backup 2>/dev/null || true
|
cp -r /opt/manyfold/app/storage /opt/manyfold_storage_backup 2>/dev/null || true
|
||||||
cp -r /opt/manyfold/app/tmp /opt/manyfold_tmp_backup 2>/dev/null || true
|
cp -r /opt/manyfold/app/tmp /opt/manyfold_tmp_backup 2>/dev/null || true
|
||||||
cp /opt/manyfold/app/config/credentials.yml.enc /opt/manyfold_credentials.yml.enc 2>/dev/null || true
|
|
||||||
cp /opt/manyfold/app/config/master.key /opt/manyfold_master.key 2>/dev/null || true
|
|
||||||
$STD tar -czf "/opt/manyfold_${CURRENT_VERSION}_backup.tar.gz" -C /opt/manyfold app
|
$STD tar -czf "/opt/manyfold_${CURRENT_VERSION}_backup.tar.gz" -C /opt/manyfold app
|
||||||
msg_ok "Backed up Data"
|
msg_ok "Backed up Data"
|
||||||
|
|
||||||
@@ -57,14 +55,12 @@ function update_script() {
|
|||||||
RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" HOME=/home/manyfold setup_ruby
|
RUBY_VERSION=${RUBY_INSTALL_VERSION} RUBY_INSTALL_RAILS="true" HOME=/home/manyfold setup_ruby
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
rm -rf /opt/manyfold/app/{storage,tmp,config/credentials.yml.enc,config/master.key}
|
rm -rf /opt/manyfold/app/{storage,tmp}
|
||||||
cp -r /opt/manyfold_storage_backup /opt/manyfold/app/storage 2>/dev/null || true
|
cp -r /opt/manyfold_storage_backup /opt/manyfold/app/storage 2>/dev/null || true
|
||||||
cp -r /opt/manyfold_tmp_backup /opt/manyfold/app/tmp 2>/dev/null || true
|
cp -r /opt/manyfold_tmp_backup /opt/manyfold/app/tmp 2>/dev/null || true
|
||||||
cp /opt/manyfold_credentials.yml.enc /opt/manyfold/app/config/credentials.yml.enc 2>/dev/null || true
|
|
||||||
cp /opt/manyfold_master.key /opt/manyfold/app/config/master.key 2>/dev/null || true
|
|
||||||
chown -R manyfold:manyfold {/home/manyfold,/opt/manyfold}
|
chown -R manyfold:manyfold {/home/manyfold,/opt/manyfold}
|
||||||
chown -R manyfold:manyfold /opt/manyfold/app/storage /opt/manyfold/app/tmp /opt/manyfold/app/config
|
chown -R manyfold:manyfold /opt/manyfold/app/storage /opt/manyfold/app/tmp /opt/manyfold/app/config
|
||||||
rm -rf /opt/manyfold_storage_backup /opt/manyfold_tmp_backup /opt/manyfold_credentials.yml.enc /opt/manyfold_master.key
|
rm -rf /opt/manyfold_storage_backup /opt/manyfold_tmp_backup
|
||||||
msg_ok "Restored Data"
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
msg_info "Installing Manyfold"
|
msg_info "Installing Manyfold"
|
||||||
@@ -80,6 +76,8 @@ function update_script() {
|
|||||||
bundle install
|
bundle install
|
||||||
corepack prepare '"$YARN_VERSION"' --activate
|
corepack prepare '"$YARN_VERSION"' --activate
|
||||||
corepack use '"$YARN_VERSION"'
|
corepack use '"$YARN_VERSION"'
|
||||||
|
rm -f config/credentials.yml.enc config/master.key
|
||||||
|
EDITOR=/bin/true bin/rails credentials:edit
|
||||||
bin/rails db:migrate
|
bin/rails db:migrate
|
||||||
bin/rails assets:precompile
|
bin/rails assets:precompile
|
||||||
'
|
'
|
||||||
|
|||||||
32
ct/mqtt.sh
32
ct/mqtt.sh
@@ -21,18 +21,28 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -f /etc/mosquitto/conf.d/default.conf ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
if [[ ! -f /etc/mosquitto/conf.d/default.conf ]]; then
|
||||||
exit
|
msg_error "No ${APP} Installation Found!"
|
||||||
fi
|
|
||||||
msg_info "Updating ${APP} LXC"
|
|
||||||
$STD apt update
|
|
||||||
$STD apt -y upgrade
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
exit
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f /etc/apt/sources.list.d/mqtt.sources ]]; then
|
||||||
|
setup_deb822_repo \
|
||||||
|
"mqtt" \
|
||||||
|
"https://repo.mosquitto.org/debian/mosquitto-repo.gpg" \
|
||||||
|
"https://repo.mosquitto.org/debian" \
|
||||||
|
"trixie"
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Updating MQTT"
|
||||||
|
$STD apt update
|
||||||
|
$STD apt upgrade -y
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
|||||||
85
ct/musicseerr.sh
Normal file
85
ct/musicseerr.sh
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: michelroegl-brunner
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://musicseerr.com/ | Github: https://github.com/HabiRabbu/Musicseerr
|
||||||
|
|
||||||
|
APP="MusicSeerr"
|
||||||
|
var_tags="${var_tags:-arr;media}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-4096}"
|
||||||
|
var_disk="${var_disk:-8}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-13}"
|
||||||
|
var_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/musicseerr ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "musicseerr" "HabiRabbu/Musicseerr"; then
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop musicseerr
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Backing up Data"
|
||||||
|
cp -a /opt/musicseerr/backend/config /opt/musicseerr_config_backup
|
||||||
|
cp -a /opt/musicseerr/backend/cache /opt/musicseerr_cache_backup
|
||||||
|
msg_ok "Backed up Data"
|
||||||
|
|
||||||
|
PYTHON_VERSION="3.13" setup_uv
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "musicseerr" "HabiRabbu/Musicseerr" "tarball"
|
||||||
|
NODE_VERSION="25" NODE_MODULE="pnpm@10.33.0" setup_nodejs
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
cd /opt/musicseerr/frontend
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
|
rm -rf node_modules build
|
||||||
|
$STD pnpm install --frozen-lockfile
|
||||||
|
$STD pnpm run build
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Updating Application"
|
||||||
|
mkdir -p /opt/musicseerr/backend/config /opt/musicseerr/backend/cache
|
||||||
|
$STD uv venv --clear /opt/musicseerr/venv
|
||||||
|
$STD uv pip install -r /opt/musicseerr/backend/requirements.txt --python=/opt/musicseerr/venv/bin/python
|
||||||
|
rm -rf /opt/musicseerr/backend/static
|
||||||
|
cp -r /opt/musicseerr/frontend/build /opt/musicseerr/backend/static
|
||||||
|
msg_ok "Updated Application"
|
||||||
|
|
||||||
|
msg_info "Restoring Data"
|
||||||
|
rm -rf /opt/musicseerr/backend/config /opt/musicseerr/backend/cache
|
||||||
|
cp -a /opt/musicseerr_config_backup/. /opt/musicseerr/backend/config/
|
||||||
|
cp -a /opt/musicseerr_cache_backup/. /opt/musicseerr/backend/cache/
|
||||||
|
rm -rf /opt/musicseerr_config_backup /opt/musicseerr_cache_backup
|
||||||
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start musicseerr
|
||||||
|
msg_ok "Started Service"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8688${CL}"
|
||||||
@@ -216,6 +216,12 @@ EOF
|
|||||||
msg_ok "Initialized Backend"
|
msg_ok "Initialized Backend"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
|
CERTBOT_VER=$(/opt/certbot/bin/certbot --version 2>&1 | awk '{print $NF}')
|
||||||
|
if grep -q "Environment=CERTBOT_VERSION" /lib/systemd/system/npm.service; then
|
||||||
|
sed -i "s|Environment=CERTBOT_VERSION=.*|Environment=CERTBOT_VERSION=${CERTBOT_VER}|" /lib/systemd/system/npm.service
|
||||||
|
else
|
||||||
|
sed -i "/Environment=NODE_ENV=production/a Environment=CERTBOT_VERSION=${CERTBOT_VER}" /lib/systemd/system/npm.service
|
||||||
|
fi
|
||||||
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||||
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
|
sed -r -i 's/^([[:space:]]*)su npm npm/\1#su npm npm/g;' /etc/logrotate.d/nginx-proxy-manager
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ function update_script() {
|
|||||||
msg_info "Updating Open Archiver"
|
msg_info "Updating Open Archiver"
|
||||||
cd /opt/openarchiver
|
cd /opt/openarchiver
|
||||||
$STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
$STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
||||||
|
$STD pnpm approve-builds --yes
|
||||||
$STD pnpm run build:oss
|
$STD pnpm run build:oss
|
||||||
$STD pnpm db:migrate
|
$STD pnpm db:migrate
|
||||||
msg_ok "Updated Open Archiver"
|
msg_ok "Updated Open Archiver"
|
||||||
|
|||||||
@@ -70,6 +70,27 @@ function update_script() {
|
|||||||
$STD ninja install
|
$STD ninja install
|
||||||
msg_ok "Rebuilt OpenThread Border Router"
|
msg_ok "Rebuilt OpenThread Border Router"
|
||||||
|
|
||||||
|
if ! grep -q "net.ipv6.conf.all.accept_ra=2" /etc/sysctl.d/99-otbr.conf; then
|
||||||
|
msg_info "Configuring Network"
|
||||||
|
cat <<EOF >/etc/sysctl.d/99-otbr.conf
|
||||||
|
net.ipv6.conf.all.forwarding=1
|
||||||
|
net.ipv6.conf.all.accept_ra=2
|
||||||
|
net.ipv6.conf.all.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.all.accept_ra_rt_info_max_plen=64
|
||||||
|
net.ipv6.conf.default.forwarding=1
|
||||||
|
net.ipv6.conf.default.accept_ra=2
|
||||||
|
net.ipv6.conf.default.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.default.accept_ra_rt_info_max_plen=64
|
||||||
|
net.ipv6.conf.eth0.forwarding=1
|
||||||
|
net.ipv6.conf.eth0.accept_ra=2
|
||||||
|
net.ipv6.conf.eth0.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.eth0.accept_ra_rt_info_max_plen=64
|
||||||
|
net.ipv4.ip_forward=1
|
||||||
|
EOF
|
||||||
|
$STD sysctl -p /etc/sysctl.d/99-otbr.conf
|
||||||
|
msg_ok "Configured Network"
|
||||||
|
fi
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
systemctl start otbr-agent
|
systemctl start otbr-agent
|
||||||
systemctl start otbr-web
|
systemctl start otbr-web
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
|
||||||
if check_for_gh_release "deno" "denoland/deno" "v2.7.5" "Deno is pinned to 2.7.5 because the known WouldBlock: Resource temporarily unavailable (os error 11) Issue"; then
|
if check_for_gh_release "deno" "denoland/deno" "v2.7.5" "Deno is pinned to 2.7.5 because the known WouldBlock: Resource temporarily unavailable (os error 11) Issue"; then
|
||||||
ARCH=$(uname -m)
|
|
||||||
fetch_and_deploy_gh_release "deno" "denoland/deno" "v2.7.5" "latest" "/usr/local/bin" "deno-${ARCH}-unknown-linux-gnu.zip"
|
fetch_and_deploy_gh_release "deno" "denoland/deno" "v2.7.5" "latest" "/usr/local/bin" "deno-${ARCH}-unknown-linux-gnu.zip"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -90,6 +91,7 @@ EOF
|
|||||||
msg_ok "Built Profilarr"
|
msg_ok "Built Profilarr"
|
||||||
|
|
||||||
msg_info "Updating Profilarr"
|
msg_info "Updating Profilarr"
|
||||||
|
mkdir -p /opt/profilarr/app
|
||||||
cp dist/build/profilarr /opt/profilarr/app/profilarr
|
cp dist/build/profilarr /opt/profilarr/app/profilarr
|
||||||
cp dist/build/server.js /opt/profilarr/app/server.js
|
cp dist/build/server.js /opt/profilarr/app/server.js
|
||||||
cp -r dist/build/static /opt/profilarr/app/static
|
cp -r dist/build/static /opt/profilarr/app/static
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
|
|
||||||
if check_for_gh_release "soulsync" "Nezreka/SoulSync"; then
|
if check_for_gh_release "soulsync" "Nezreka/SoulSync"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ EOF
|
|||||||
msg_ok "Updated Sure"
|
msg_ok "Updated Sure"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
$STD systemctl start sure sure-worker
|
systemctl start sure sure-worker
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Installing Python Dependencies"
|
msg_info "Installing Python Dependencies"
|
||||||
cd /opt/yamtrack
|
cd /opt/yamtrack
|
||||||
$STD uv venv --clear .venv
|
$STD uv sync --locked
|
||||||
$STD uv pip install --no-cache-dir -r requirements.txt
|
|
||||||
msg_ok "Installed Python Dependencies"
|
msg_ok "Installed Python Dependencies"
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ After=network-online.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/apprise
|
WorkingDirectory=/opt/apprise
|
||||||
ExecStart=/opt/apprise/webapp/supervisord-startup
|
ExecStart=/opt/apprise/webapp/supervisord-startup
|
||||||
|
Environment=APPRISE_CONFIG_DIR=/config
|
||||||
|
Environment=APPRISE_ATTACH_DIR=/attach
|
||||||
|
Environment=APPRISE_PLUGIN_PATHS=/plugin
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=30
|
RestartSec=30
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ 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
|
||||||
chmod +x /usr/local/bin/birdnet-go
|
chmod +x /usr/local/bin/birdnet-go
|
||||||
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
|
cp -r /opt/birdnet/libtensorflowlite_c.so /usr/local/lib/ || true
|
||||||
|
cp -r /opt/birdnet/libonnxruntime.so /usr/local/lib/ || true
|
||||||
ldconfig
|
ldconfig
|
||||||
mkdir -p /opt/birdnet/data/clips
|
mkdir -p /opt/birdnet/data/clips
|
||||||
msg_ok "Set up BirdNET-Go"
|
msg_ok "Set up BirdNET-Go"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
|
|||||||
$STD apt install -y build-essential
|
$STD apt install -y build-essential
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="24" setup_nodejs
|
NODE_VERSION="26" setup_nodejs
|
||||||
|
|
||||||
msg_info "Setup Cross-Seed"
|
msg_info "Setup Cross-Seed"
|
||||||
$STD npm install cross-seed@latest -g
|
$STD npm install cross-seed@latest -g
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ update_os
|
|||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt install -y \
|
$STD apt install -y \
|
||||||
git \
|
git \
|
||||||
unzip
|
unzip \
|
||||||
|
valkey
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
msg_info "Installing Bun"
|
msg_info "Installing Bun"
|
||||||
@@ -38,6 +39,9 @@ DEGOOG_PLUGINS_DIR=/opt/degoog/data/plugins
|
|||||||
DEGOOG_THEMES_DIR=/opt/degoog/data/themes
|
DEGOOG_THEMES_DIR=/opt/degoog/data/themes
|
||||||
DEGOOG_ALIASES_FILE=/opt/degoog/data/aliases.json
|
DEGOOG_ALIASES_FILE=/opt/degoog/data/aliases.json
|
||||||
DEGOOG_PLUGIN_SETTINGS_FILE=/opt/degoog/data/plugin-settings.json
|
DEGOOG_PLUGIN_SETTINGS_FILE=/opt/degoog/data/plugin-settings.json
|
||||||
|
DEGOOG_VALKEY_URL=redis://valkey:6379
|
||||||
|
DEGOOG_CACHE_MAX_ENTRIES=1000
|
||||||
|
DEGOOG_CACHE_TTL_MS=43200000
|
||||||
# DEGOOG_SETTINGS_PASSWORDS=changeme
|
# DEGOOG_SETTINGS_PASSWORDS=changeme
|
||||||
# DEGOOG_PUBLIC_INSTANCE=false
|
# DEGOOG_PUBLIC_INSTANCE=false
|
||||||
# LOGGER=debug
|
# LOGGER=debug
|
||||||
@@ -62,11 +66,16 @@ EOF
|
|||||||
fi
|
fi
|
||||||
msg_ok "Set up degoog"
|
msg_ok "Set up degoog"
|
||||||
|
|
||||||
|
msg_info "Starting Valkey Service"
|
||||||
|
systemctl enable -q --now valkey-server
|
||||||
|
msg_ok "Started Valkey Service"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
cat <<EOF >/etc/systemd/system/degoog.service
|
cat <<EOF >/etc/systemd/system/degoog.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=degoog
|
Description=degoog
|
||||||
After=network.target
|
After=network.target valkey-server.service
|
||||||
|
Wants=valkey-server.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ server {
|
|||||||
# All other requests proxy to uWSGI
|
# All other requests proxy to uWSGI
|
||||||
location / {
|
location / {
|
||||||
include proxy_params;
|
include proxy_params;
|
||||||
|
proxy_set_header X-Forwarded-Port \$server_port;
|
||||||
proxy_pass http://127.0.0.1:5656;
|
proxy_pass http://127.0.0.1:5656;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ $STD apt install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||||
RUBY_VERSION="4.0.1" RUBY_INSTALL_RAILS="false" HOME=/root setup_ruby
|
|
||||||
PG_VERSION="17" setup_postgresql
|
PG_VERSION="17" setup_postgresql
|
||||||
PG_DB_NAME="docuseal" PG_DB_USER="docuseal" setup_postgresql_db
|
PG_DB_NAME="docuseal" PG_DB_USER="docuseal" setup_postgresql_db
|
||||||
|
|
||||||
@@ -56,6 +55,9 @@ msg_ok "Downloaded Fonts and PDFium"
|
|||||||
|
|
||||||
fetch_and_deploy_gh_release "docuseal" "docusealco/docuseal" "tarball"
|
fetch_and_deploy_gh_release "docuseal" "docusealco/docuseal" "tarball"
|
||||||
|
|
||||||
|
RUBY_VERSION=$(grep -m1 '^ruby ' /opt/docuseal/Gemfile | grep -oP '[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
|
RUBY_VERSION="${RUBY_VERSION}" RUBY_INSTALL_RAILS="false" HOME=/root setup_ruby
|
||||||
|
|
||||||
msg_info "Downloading Field Detection Model"
|
msg_info "Downloading Field Detection Model"
|
||||||
mkdir -p /opt/docuseal/tmp
|
mkdir -p /opt/docuseal/tmp
|
||||||
curl -fsSL -o /opt/docuseal/tmp/model.onnx \
|
curl -fsSL -o /opt/docuseal/tmp/model.onnx \
|
||||||
|
|||||||
71
install/dynacat-install.sh
Normal file
71
install/dynacat-install.sh
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/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/Panonim/dynacat
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "dynacat" "Panonim/dynacat" "prebuild" "latest" "/opt/dynacat" "dynacat-linux-amd64.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Setting up Dynacat"
|
||||||
|
mkdir -p /opt/dynacat/config /opt/dynacat/assets /opt/dynacat/data
|
||||||
|
chmod +x /opt/dynacat/dynacat
|
||||||
|
|
||||||
|
cat <<EOF >/opt/dynacat/config/dynacat.yml
|
||||||
|
server:
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 8080
|
||||||
|
assets-path: /opt/dynacat/assets
|
||||||
|
db-path: /opt/dynacat/data/dynacat.db
|
||||||
|
|
||||||
|
pages:
|
||||||
|
- name: Home
|
||||||
|
columns:
|
||||||
|
- size: small
|
||||||
|
widgets:
|
||||||
|
- type: calendar
|
||||||
|
- type: clock
|
||||||
|
- size: full
|
||||||
|
widgets:
|
||||||
|
- type: search
|
||||||
|
search-engine: duckduckgo
|
||||||
|
- type: monitor
|
||||||
|
title: Services
|
||||||
|
sites:
|
||||||
|
- title: Dynacat
|
||||||
|
url: http://127.0.0.1:8080
|
||||||
|
update-interval: 5m
|
||||||
|
EOF
|
||||||
|
msg_ok "Set up Dynacat"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/dynacat.service
|
||||||
|
[Unit]
|
||||||
|
Description=Dynacat Dashboard
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/dynacat
|
||||||
|
ExecStart=/opt/dynacat/dynacat -config /opt/dynacat/config/dynacat.yml
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now dynacat
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -37,7 +37,13 @@ msg_ok "Configured Firefly III"
|
|||||||
|
|
||||||
msg_info "Configuring Data Importer"
|
msg_info "Configuring Data Importer"
|
||||||
cp /opt/firefly/dataimporter/.env.example /opt/firefly/dataimporter/.env
|
cp /opt/firefly/dataimporter/.env.example /opt/firefly/dataimporter/.env
|
||||||
sed -i "s#FIREFLY_III_URL=#FIREFLY_III_URL=http://${LOCAL_IP}#g" /opt/firefly/dataimporter/.env
|
sed -i \
|
||||||
|
-e "s#FIREFLY_III_URL=#FIREFLY_III_URL=http://${LOCAL_IP}#g" \
|
||||||
|
-e "s|^APP_URL=.*|APP_URL=http://${LOCAL_IP}/dataimporter|" \
|
||||||
|
-e "s|^ASSET_URL=.*|ASSET_URL=/dataimporter|" \
|
||||||
|
/opt/firefly/dataimporter/.env
|
||||||
|
cd /opt/firefly/dataimporter
|
||||||
|
$STD php artisan config:clear
|
||||||
chown -R www-data:www-data /opt/firefly
|
chown -R www-data:www-data /opt/firefly
|
||||||
msg_ok "Configured Data Importer"
|
msg_ok "Configured Data Importer"
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ NODE_VERSION="22" setup_nodejs
|
|||||||
|
|
||||||
msg_info "Setting up Flatnotes"
|
msg_info "Setting up Flatnotes"
|
||||||
cd /opt/flatnotes
|
cd /opt/flatnotes
|
||||||
|
sed -i 's/^name = ""$/name = "flatnotes"/' pyproject.toml
|
||||||
$STD /usr/local/bin/uvx migrate-to-uv
|
$STD /usr/local/bin/uvx migrate-to-uv
|
||||||
$STD /usr/local/bin/uv sync
|
$STD /usr/local/bin/uv sync
|
||||||
mkdir -p /opt/flatnotes/data
|
mkdir -p /opt/flatnotes/data
|
||||||
|
|||||||
124
install/hermesagent-install.sh
Normal file
124
install/hermesagent-install.sh
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: Stephen Chin (steveonjava)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://hermes-agent.nousresearch.com/
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
msg_info "Installing Dependencies"
|
||||||
|
$STD apt install -y git
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
NODE_VERSION="22" setup_nodejs
|
||||||
|
|
||||||
|
msg_info "Creating Hermes User"
|
||||||
|
useradd -m -s /bin/bash hermes
|
||||||
|
loginctl enable-linger hermes
|
||||||
|
echo 'export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"' >>/home/hermes/.profile
|
||||||
|
msg_ok "Created Hermes User"
|
||||||
|
|
||||||
|
msg_info "Configuring Service Environment"
|
||||||
|
cat <<EOF >/etc/default/hermes
|
||||||
|
HOME=/home/hermes
|
||||||
|
PATH=/home/hermes/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
NODE_OPTIONS=${NODE_OPTIONS}
|
||||||
|
EOF
|
||||||
|
msg_ok "Configured Service Environment"
|
||||||
|
|
||||||
|
msg_warn "WARNING: This script will run an external installer from a third-party source (https://hermes-agent.nousresearch.com/)."
|
||||||
|
msg_warn "The following code is NOT maintained or audited by our repository."
|
||||||
|
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
|
||||||
|
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://hermes-agent.nousresearch.com/install.sh"
|
||||||
|
echo
|
||||||
|
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
|
||||||
|
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||||
|
msg_error "Aborted by user. No changes have been made."
|
||||||
|
exit 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Installing Hermes Agent"
|
||||||
|
$STD setsid --wait bash -c '
|
||||||
|
set -a; source /etc/default/hermes; set +a
|
||||||
|
export npm_config_yes=true
|
||||||
|
bash <(curl -fsSL https://hermes-agent.nousresearch.com/install.sh) --skip-setup --hermes-home /home/hermes/.hermes --dir /home/hermes/.hermes/hermes-agent
|
||||||
|
'
|
||||||
|
chown -R hermes:hermes /home/hermes
|
||||||
|
chmod 750 /home/hermes
|
||||||
|
chmod 700 /home/hermes/.hermes
|
||||||
|
git config --system --add safe.directory /home/hermes/.hermes/hermes-agent 2>/dev/null || true
|
||||||
|
msg_ok "Installed Hermes Agent"
|
||||||
|
|
||||||
|
msg_info "Configuring API Server"
|
||||||
|
API_SERVER_KEY=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)
|
||||||
|
mkdir -p /home/hermes/.hermes
|
||||||
|
cat <<EOF >/home/hermes/.hermes/.env
|
||||||
|
API_SERVER_ENABLED=true
|
||||||
|
API_SERVER_HOST=0.0.0.0
|
||||||
|
API_SERVER_PORT=8642
|
||||||
|
API_SERVER_KEY=${API_SERVER_KEY}
|
||||||
|
EOF
|
||||||
|
chmod 600 /home/hermes/.hermes/.env
|
||||||
|
msg_ok "Configured API Server"
|
||||||
|
|
||||||
|
msg_info "Creating Dashboard Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/hermes-dashboard.service
|
||||||
|
[Unit]
|
||||||
|
Description=Hermes Agent Web Dashboard
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=hermes
|
||||||
|
Group=hermes
|
||||||
|
UMask=0077
|
||||||
|
WorkingDirectory=/home/hermes
|
||||||
|
ExecStart=/home/hermes/.local/bin/hermes dashboard --host 127.0.0.1 --port 9119 --no-open
|
||||||
|
EnvironmentFile=/etc/default/hermes
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
ProtectProc=invisible
|
||||||
|
ProcSubset=pid
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now hermes-dashboard
|
||||||
|
msg_ok "Created Dashboard Service"
|
||||||
|
|
||||||
|
msg_info "Creating Setup Helper"
|
||||||
|
cat <<'SETUP' >/usr/bin/hermes-setup
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -a; source /etc/default/hermes; set +a
|
||||||
|
/home/hermes/.local/bin/hermes setup
|
||||||
|
chown -R hermes:hermes /home/hermes
|
||||||
|
chmod 750 /home/hermes
|
||||||
|
chmod 700 /home/hermes/.hermes
|
||||||
|
if [[ -f /home/hermes/.config/systemd/user/hermes-gateway.service ]]; then
|
||||||
|
su - hermes -c 'systemctl --user enable --now hermes-gateway'
|
||||||
|
fi
|
||||||
|
echo "Hermes setup complete. File permissions restored."
|
||||||
|
SETUP
|
||||||
|
chmod +x /usr/bin/hermes-setup
|
||||||
|
msg_ok "Created Setup Helper"
|
||||||
|
|
||||||
|
msg_info "Configuring Login Hints"
|
||||||
|
cat <<'HINT' >/etc/profile.d/hermes-hint.sh
|
||||||
|
if [[ "$(id -u)" -eq 0 ]]; then
|
||||||
|
echo " Run 'hermes-setup' to configure your model provider and gateway server."
|
||||||
|
echo " Use 'su - hermes' (with the dash) to switch to the hermes user."
|
||||||
|
fi
|
||||||
|
HINT
|
||||||
|
msg_ok "Configured Login Hints"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -13,12 +13,12 @@ setting_up_container
|
|||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
|
||||||
if ! grep -q ' avx ' /proc/cpuinfo 2>/dev/null; then
|
ISBTV_BINARY="iSponsorBlockTV-x86_64-linux-v1"
|
||||||
msg_error "CPU does not support AVX instructions (required by iSponsorBlockTV/PyApp)"
|
if grep -q ' avx ' /proc/cpuinfo 2>/dev/null && grep -q ' avx2 ' /proc/cpuinfo 2>/dev/null && grep -q ' movbe ' /proc/cpuinfo 2>/dev/null; then
|
||||||
exit 106
|
ISBTV_BINARY="iSponsorBlockTV-x86_64-linux"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "iSponsorBlockTV-x86_64-linux"
|
fetch_and_deploy_gh_release "isponsorblocktv" "dmunozv04/iSponsorBlockTV" "singlefile" "latest" "/opt/isponsorblocktv" "${ISBTV_BINARY}"
|
||||||
|
|
||||||
msg_info "Setting up iSponsorBlockTV"
|
msg_info "Setting up iSponsorBlockTV"
|
||||||
install -d /var/lib/isponsorblocktv
|
install -d /var/lib/isponsorblocktv
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Type=simple
|
|||||||
WorkingDirectory=/opt/Jackett
|
WorkingDirectory=/opt/Jackett
|
||||||
ExecStart=/bin/sh /opt/Jackett/jackett_launcher.sh
|
ExecStart=/bin/sh /opt/Jackett/jackett_launcher.sh
|
||||||
TimeoutStopSec=30
|
TimeoutStopSec=30
|
||||||
EnvironmentFile="/opt/.env"
|
EnvironmentFile=/opt/.env
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
90
install/kan-install.sh
Normal file
90
install/kan-install.sh
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#!/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/kanbn/kan
|
||||||
|
|
||||||
|
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
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
PG_VERSION="16" setup_postgresql
|
||||||
|
PG_DB_NAME="kan" PG_DB_USER="kan" setup_postgresql_db
|
||||||
|
NODE_VERSION="20" NODE_MODULE="pnpm" setup_nodejs
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_tag "kan" "kanbn/kan" "latest"
|
||||||
|
|
||||||
|
msg_info "Configuring Application"
|
||||||
|
AUTH_SECRET=$(openssl rand -base64 32)
|
||||||
|
cat <<EOF >/opt/kan/.env
|
||||||
|
NEXT_PUBLIC_BASE_URL=http://${LOCAL_IP}:3000
|
||||||
|
BETTER_AUTH_SECRET=${AUTH_SECRET}
|
||||||
|
BETTER_AUTH_TRUSTED_ORIGINS=http://${LOCAL_IP}:3000
|
||||||
|
POSTGRES_URL=postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
|
||||||
|
NEXT_PUBLIC_ALLOW_CREDENTIALS=true
|
||||||
|
TRELLO_APP_API_KEY=
|
||||||
|
TRELLO_APP_API_SECRET=
|
||||||
|
HOSTNAME=0.0.0.0
|
||||||
|
PORT=3000
|
||||||
|
NODE_ENV=production
|
||||||
|
EOF
|
||||||
|
msg_ok "Configured Application"
|
||||||
|
|
||||||
|
msg_info "Building Application"
|
||||||
|
cd /opt/kan
|
||||||
|
set -a && source /opt/kan/.env && set +a
|
||||||
|
export NEXT_PUBLIC_USE_STANDALONE_OUTPUT=true NEXT_PUBLIC_BASE_URL BETTER_AUTH_TRUSTED_ORIGINS NEXT_PUBLIC_ALLOW_CREDENTIALS BETTER_AUTH_SECRET
|
||||||
|
$STD pnpm install --ignore-scripts --prod=false
|
||||||
|
export CI=true
|
||||||
|
find /opt/kan/packages /opt/kan/apps -name 'tsconfig.json' -exec sed -i 's|"@kan/tsconfig/|"../../tooling/typescript/|g' {} +
|
||||||
|
$STD pnpm build --filter=@kan/web
|
||||||
|
unset NEXT_PUBLIC_USE_STANDALONE_OUTPUT CI
|
||||||
|
msg_ok "Built Application"
|
||||||
|
|
||||||
|
msg_info "Setting up Standalone"
|
||||||
|
mkdir -p /opt/kan/apps/web/.next/standalone/apps/web/.next/static
|
||||||
|
cp -r /opt/kan/apps/web/.next/static/* /opt/kan/apps/web/.next/standalone/apps/web/.next/static/
|
||||||
|
cp -r /opt/kan/apps/web/public /opt/kan/apps/web/.next/standalone/apps/web/public
|
||||||
|
msg_ok "Set up Standalone"
|
||||||
|
|
||||||
|
msg_info "Running Database Migrations"
|
||||||
|
cd /opt/kan/packages/db
|
||||||
|
POSTGRES_URL="postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}" $STD pnpm exec drizzle-kit migrate
|
||||||
|
msg_ok "Ran Database Migrations"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/kan.service
|
||||||
|
[Unit]
|
||||||
|
Description=Kan Board
|
||||||
|
After=network.target postgresql.service
|
||||||
|
Requires=postgresql.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/kan/apps/web/.next/standalone
|
||||||
|
EnvironmentFile=/opt/kan/.env
|
||||||
|
ExecStart=/usr/bin/node apps/web/server.js
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now kan
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -36,6 +36,11 @@ NODE_VERSION="24" NODE_MODULE="pnpm@${MODULE_VERSION}" setup_nodejs
|
|||||||
|
|
||||||
msg_info "Installing external JavaScript Extension for yt-dlp"
|
msg_info "Installing external JavaScript Extension for yt-dlp"
|
||||||
$STD pip install -U yt-dlp-ejs
|
$STD pip install -U yt-dlp-ejs
|
||||||
|
mkdir -p ~/.config/pip
|
||||||
|
cat <<EOF >~/.config/pip/pip.conf
|
||||||
|
[global]
|
||||||
|
break-system-packages = true
|
||||||
|
EOF
|
||||||
msg_ok "Installed external JavaScript Extension for yt-dlp"
|
msg_ok "Installed external JavaScript Extension for yt-dlp"
|
||||||
|
|
||||||
msg_info "Installing karakeep"
|
msg_info "Installing karakeep"
|
||||||
|
|||||||
@@ -56,20 +56,20 @@ msg_ok "Installed Python Dependencies"
|
|||||||
msg_info "Downloading Essentia ML Models"
|
msg_info "Downloading Essentia ML Models"
|
||||||
mkdir -p /opt/kima-hub/models
|
mkdir -p /opt/kima-hub/models
|
||||||
cd /opt/kima-hub/models
|
cd /opt/kima-hub/models
|
||||||
curl -fsSL -o msd-musicnn-1.pb "https://essentia.upf.edu/models/autotagging/msd/msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/autotagging/msd/msd-musicnn-1.pb" "msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_happy-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_happy/mood_happy-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_happy/mood_happy-msd-musicnn-1.pb" "mood_happy-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_sad-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_sad/mood_sad-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_sad/mood_sad-msd-musicnn-1.pb" "mood_sad-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_relaxed-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_relaxed/mood_relaxed-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_relaxed/mood_relaxed-msd-musicnn-1.pb" "mood_relaxed-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_aggressive-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_aggressive/mood_aggressive-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_aggressive/mood_aggressive-msd-musicnn-1.pb" "mood_aggressive-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_party-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_party/mood_party-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_party/mood_party-msd-musicnn-1.pb" "mood_party-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_acoustic-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_acoustic/mood_acoustic-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_acoustic/mood_acoustic-msd-musicnn-1.pb" "mood_acoustic-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o mood_electronic-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/mood_electronic/mood_electronic-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/mood_electronic/mood_electronic-msd-musicnn-1.pb" "mood_electronic-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o danceability-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/danceability/danceability-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/danceability/danceability-msd-musicnn-1.pb" "danceability-msd-musicnn-1.pb"
|
||||||
curl -fsSL -o voice_instrumental-msd-musicnn-1.pb "https://essentia.upf.edu/models/classification-heads/voice_instrumental/voice_instrumental-msd-musicnn-1.pb"
|
curl_with_retry "https://essentia.upf.edu/models/classification-heads/voice_instrumental/voice_instrumental-msd-musicnn-1.pb" "voice_instrumental-msd-musicnn-1.pb"
|
||||||
msg_ok "Downloaded Essentia ML Models"
|
msg_ok "Downloaded Essentia ML Models"
|
||||||
|
|
||||||
msg_info "Downloading CLAP Model"
|
msg_info "Downloading CLAP Model"
|
||||||
curl -fsSL -o /opt/kima-hub/models/music_audioset_epoch_15_esc_90.14.pt "https://huggingface.co/lukewys/laion_clap/resolve/main/music_audioset_epoch_15_esc_90.14.pt"
|
CURL_TIMEOUT=600 curl_with_retry "https://huggingface.co/lukewys/laion_clap/resolve/main/music_audioset_epoch_15_esc_90.14.pt" "/opt/kima-hub/models/music_audioset_epoch_15_esc_90.14.pt"
|
||||||
msg_ok "Downloaded CLAP Model"
|
msg_ok "Downloaded CLAP Model"
|
||||||
|
|
||||||
msg_info "Building Backend"
|
msg_info "Building Backend"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ setting_up_container
|
|||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
|
||||||
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
|
NODE_VERSION="26" NODE_MODULE="yarn" setup_nodejs
|
||||||
PG_VERSION="16" setup_postgresql
|
PG_VERSION="16" setup_postgresql
|
||||||
PHP_VERSION="8.5" PHP_APACHE="YES" setup_php
|
PHP_VERSION="8.5" PHP_APACHE="YES" setup_php
|
||||||
setup_composer
|
setup_composer
|
||||||
|
|||||||
@@ -13,18 +13,26 @@ setting_up_container
|
|||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
|
||||||
msg_info "Installing Mosquitto MQTT Broker"
|
setup_deb822_repo \
|
||||||
source /etc/os-release
|
"mqtt" \
|
||||||
$STD apt update
|
"https://repo.mosquitto.org/debian/mosquitto-repo.gpg" \
|
||||||
$STD apt -y install mosquitto mosquitto-clients
|
"https://repo.mosquitto.org/debian" \
|
||||||
|
"trixie"
|
||||||
|
|
||||||
|
msg_info "Installing Mosquitto MQTT Broker"
|
||||||
|
$STD apt install -y \
|
||||||
|
mosquitto \
|
||||||
|
mosquitto-clients
|
||||||
|
msg_ok "Installed Mosquitto MQTT Broker"
|
||||||
|
|
||||||
|
msg_info "Configuring Mosquitto MQTT Broker"
|
||||||
cat <<EOF >/etc/mosquitto/conf.d/default.conf
|
cat <<EOF >/etc/mosquitto/conf.d/default.conf
|
||||||
allow_anonymous false
|
allow_anonymous false
|
||||||
persistence true
|
persistence true
|
||||||
password_file /etc/mosquitto/passwd
|
password_file /etc/mosquitto/passwd
|
||||||
listener 1883
|
listener 1883
|
||||||
EOF
|
EOF
|
||||||
msg_ok "Installed Mosquitto MQTT Broker"
|
msg_ok "Configured Mosquitto MQTT Broker"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
|
|||||||
59
install/musicseerr-install.sh
Normal file
59
install/musicseerr-install.sh
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 community-scripts ORG
|
||||||
|
# Author: michelroegl-brunner
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://musicseerr.com/ | Github: https://github.com/HabiRabbu/Musicseerr
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
PYTHON_VERSION="3.13" setup_uv
|
||||||
|
fetch_and_deploy_gh_release "musicseerr" "HabiRabbu/Musicseerr" "tarball"
|
||||||
|
NODE_VERSION="25" NODE_MODULE="pnpm@10.33.0" setup_nodejs
|
||||||
|
|
||||||
|
msg_info "Building Frontend"
|
||||||
|
cd /opt/musicseerr/frontend
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
|
$STD pnpm install --frozen-lockfile
|
||||||
|
$STD pnpm run build
|
||||||
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
|
msg_info "Setting up Application"
|
||||||
|
mkdir -p /opt/musicseerr/backend/config /opt/musicseerr/backend/cache
|
||||||
|
$STD uv venv /opt/musicseerr/venv
|
||||||
|
$STD uv pip install -r /opt/musicseerr/backend/requirements.txt --python=/opt/musicseerr/venv/bin/python
|
||||||
|
rm -rf /opt/musicseerr/backend/static
|
||||||
|
cp -r /opt/musicseerr/frontend/build /opt/musicseerr/backend/static
|
||||||
|
msg_ok "Set up Application"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/musicseerr.service
|
||||||
|
[Unit]
|
||||||
|
Description=MusicSeerr Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=/opt/musicseerr/backend
|
||||||
|
Environment=ROOT_APP_DIR=/opt/musicseerr/backend
|
||||||
|
Environment=PORT=8688
|
||||||
|
ExecStart=/opt/musicseerr/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8688 --loop uvloop --http httptools --workers 1
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now musicseerr
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -160,7 +160,8 @@ $STD yarn install --network-timeout 600000
|
|||||||
msg_ok "Initialized Backend"
|
msg_ok "Initialized Backend"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
cat <<'EOF' >/lib/systemd/system/npm.service
|
CERTBOT_VER=$(/opt/certbot/bin/certbot --version 2>&1 | awk '{print $NF}')
|
||||||
|
cat <<EOF >/lib/systemd/system/npm.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Nginx Proxy Manager
|
Description=Nginx Proxy Manager
|
||||||
After=network.target
|
After=network.target
|
||||||
@@ -169,6 +170,7 @@ Wants=openresty.service
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
Environment=NODE_ENV=production
|
Environment=NODE_ENV=production
|
||||||
|
Environment=CERTBOT_VERSION=${CERTBOT_VER}
|
||||||
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
|
ExecStartPre=-mkdir -p /tmp/nginx/body /data/letsencrypt-acme-challenge
|
||||||
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
|
ExecStart=/usr/bin/node index.js --abort_on_uncaught_exception --max_old_space_size=250
|
||||||
WorkingDirectory=/app
|
WorkingDirectory=/app
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ sed -i "s|^ENCRYPTION_KEY=.*|ENCRYPTION_KEY=$SECRET_KEY|g" /opt/openarchiver/.en
|
|||||||
sed -i "s|^TIKA_URL=.*|TIKA_URL=|g" /opt/openarchiver/.env
|
sed -i "s|^TIKA_URL=.*|TIKA_URL=|g" /opt/openarchiver/.env
|
||||||
sed -i "s|^ORIGIN=.*|ORIGIN=http://$LOCAL_IP:3000|g" /opt/openarchiver/.env
|
sed -i "s|^ORIGIN=.*|ORIGIN=http://$LOCAL_IP:3000|g" /opt/openarchiver/.env
|
||||||
$STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
$STD pnpm install --shamefully-hoist --frozen-lockfile --prod=false
|
||||||
|
$STD pnpm approve-builds
|
||||||
$STD pnpm run build:oss
|
$STD pnpm run build:oss
|
||||||
$STD pnpm db:migrate
|
$STD pnpm db:migrate
|
||||||
msg_ok "Setup Open Archiver"
|
msg_ok "Setup Open Archiver"
|
||||||
|
|||||||
@@ -67,6 +67,17 @@ msg_ok "Built OpenThread Border Router"
|
|||||||
msg_info "Configuring Network"
|
msg_info "Configuring Network"
|
||||||
cat <<EOF >/etc/sysctl.d/99-otbr.conf
|
cat <<EOF >/etc/sysctl.d/99-otbr.conf
|
||||||
net.ipv6.conf.all.forwarding=1
|
net.ipv6.conf.all.forwarding=1
|
||||||
|
net.ipv6.conf.all.accept_ra=2
|
||||||
|
net.ipv6.conf.all.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.all.accept_ra_rt_info_max_plen=64
|
||||||
|
net.ipv6.conf.default.forwarding=1
|
||||||
|
net.ipv6.conf.default.accept_ra=2
|
||||||
|
net.ipv6.conf.default.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.default.accept_ra_rt_info_max_plen=64
|
||||||
|
net.ipv6.conf.eth0.forwarding=1
|
||||||
|
net.ipv6.conf.eth0.accept_ra=2
|
||||||
|
net.ipv6.conf.eth0.accept_ra_rtr_pref=1
|
||||||
|
net.ipv6.conf.eth0.accept_ra_rt_info_max_plen=64
|
||||||
net.ipv4.ip_forward=1
|
net.ipv4.ip_forward=1
|
||||||
EOF
|
EOF
|
||||||
$STD sysctl -p /etc/sysctl.d/99-otbr.conf
|
$STD sysctl -p /etc/sysctl.d/99-otbr.conf
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ $STD apt install -y \
|
|||||||
nginx
|
nginx
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
msg_info "Installing Nginx mod_zip module"
|
||||||
|
setup_deb822_repo \
|
||||||
|
"getpagespeed-extras" \
|
||||||
|
"https://extras.getpagespeed.com/deb-archive-keyring.gpg" \
|
||||||
|
"https://extras.getpagespeed.com/debian" \
|
||||||
|
"$(get_os_info codename)" \
|
||||||
|
"main"
|
||||||
|
$STD apt-get install -y nginx nginx-module-zip
|
||||||
|
msg_ok "Installed Nginx mod_zip module"
|
||||||
|
|
||||||
PYTHON_VERSION="3.13" setup_uv
|
PYTHON_VERSION="3.13" setup_uv
|
||||||
NODE_VERSION="24" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
setup_mariadb
|
setup_mariadb
|
||||||
@@ -255,6 +265,7 @@ EOF
|
|||||||
|
|
||||||
sed -i "s|alias /var/lib/romm/library/;|alias ${ROMM_BASE}/library/;|" /etc/nginx/sites-available/romm
|
sed -i "s|alias /var/lib/romm/library/;|alias ${ROMM_BASE}/library/;|" /etc/nginx/sites-available/romm
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
|
rm -f /etc/nginx/conf.d/default.conf
|
||||||
ln -sf /etc/nginx/sites-available/romm /etc/nginx/sites-enabled/romm
|
ln -sf /etc/nginx/sites-available/romm /etc/nginx/sites-enabled/romm
|
||||||
systemctl restart nginx
|
systemctl restart nginx
|
||||||
systemctl enable -q --now nginx
|
systemctl enable -q --now nginx
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ $STD apt install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
UV_PYTHON="3.11" setup_uv
|
UV_PYTHON="3.11" setup_uv
|
||||||
NODE_VERSION="22" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "soulsync" "Nezreka/SoulSync" "tarball"
|
fetch_and_deploy_gh_release "soulsync" "Nezreka/SoulSync" "tarball"
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ StandardError=journal
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
$STD systemctl enable -q --now sure sure-worker
|
systemctl enable -q --now sure sure-worker
|
||||||
msg_ok "Created Services"
|
msg_ok "Created Services"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
|
|||||||
@@ -41,29 +41,27 @@ cat <<EOF >/etc/caddy/Caddyfile
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
usermod -aG www-data caddy
|
usermod -aG www-data caddy
|
||||||
msg_ok "Configured Caddy"
|
|
||||||
|
|
||||||
systemctl enable -q --now php${PHP_VER}-fpm
|
systemctl enable -q --now php${PHP_VER}-fpm
|
||||||
systemctl restart caddy
|
systemctl restart caddy
|
||||||
|
msg_ok "Configured Caddy"
|
||||||
|
|
||||||
msg_info "Automating Webtrees Setup"
|
msg_info "Automating Webtrees Setup"
|
||||||
sleep 5
|
cd /opt/webtrees
|
||||||
WT_ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c15)
|
WT_ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c15)
|
||||||
curl -sS -X POST "http://127.0.0.1/" \
|
$STD sudo -u www-data php /opt/webtrees/index.php config-ini \
|
||||||
-d "step=6" \
|
--dbhost=127.0.0.1 \
|
||||||
--data-urlencode "baseurl=http://${LOCAL_IP}" \
|
--dbport=3306 \
|
||||||
-d "lang=en-US" \
|
--dbuser=webtrees \
|
||||||
-d "dbtype=mysql" \
|
--dbpass="${MARIADB_DB_PASS}" \
|
||||||
-d "dbhost=127.0.0.1" \
|
--dbname=webtrees \
|
||||||
-d "dbport=3306" \
|
--tblpfx=wt_ \
|
||||||
-d "dbuser=webtrees" \
|
--base-url="http://${LOCAL_IP}"
|
||||||
--data-urlencode "dbpass=${MARIADB_DB_PASS}" \
|
$STD sudo -u www-data php /opt/webtrees/index.php user Admin \
|
||||||
-d "dbname=webtrees" \
|
--create \
|
||||||
-d "tblpfx=wt_" \
|
--real-name="Administrator" \
|
||||||
-d "wtname=Administrator" \
|
--email="admin@example.com" \
|
||||||
-d "wtuser=Admin" \
|
--password="${WT_ADMIN_PASS}"
|
||||||
--data-urlencode "wtpass=${WT_ADMIN_PASS}" \
|
$STD sudo -u www-data php /opt/webtrees/index.php user-setting Admin canadmin 1
|
||||||
-d "wtemail=admin@example.com" >/dev/null
|
|
||||||
|
|
||||||
cat <<EOF >>~/webtrees.creds
|
cat <<EOF >>~/webtrees.creds
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ fetch_and_deploy_gh_release "yamtrack" "FuzzyGrim/Yamtrack" "tarball"
|
|||||||
|
|
||||||
msg_info "Installing Python Dependencies"
|
msg_info "Installing Python Dependencies"
|
||||||
cd /opt/yamtrack
|
cd /opt/yamtrack
|
||||||
$STD uv venv .venv
|
$STD uv sync --locked
|
||||||
$STD uv pip install --no-cache-dir -r requirements.txt
|
|
||||||
msg_ok "Installed Python Dependencies"
|
msg_ok "Installed Python Dependencies"
|
||||||
|
|
||||||
msg_info "Configuring Yamtrack"
|
msg_info "Configuring Yamtrack"
|
||||||
|
|||||||
@@ -358,6 +358,55 @@ error_handler() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── Log-pattern analysis: detect common failure causes and emit actionable hints ──
|
||||||
|
if [[ -n "$active_log" && -s "$active_log" ]]; then
|
||||||
|
local _log_tail
|
||||||
|
_log_tail=$(tail -n 60 "$active_log" 2>/dev/null || true)
|
||||||
|
|
||||||
|
# 1. APT/dpkg dependency conflict
|
||||||
|
if echo "$_log_tail" | grep -qE "Depends:|depends on.*but.*not installed|broken packages|unmet dep|dependency problems"; then
|
||||||
|
# Check for PostgreSQL-specific version mismatch (most actionable)
|
||||||
|
local _pg_conflict
|
||||||
|
_pg_conflict=$(echo "$_log_tail" | grep -oE 'postgresql-[0-9]+ but.*installed' | head -1 || true)
|
||||||
|
if [[ -n "$_pg_conflict" ]]; then
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "PostgreSQL version conflict: ${_pg_conflict}"
|
||||||
|
msg_warn "Hint: A package requires a specific PostgreSQL version that is not installed. Your distribution may have installed a different PG version than expected."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "APT dependency conflict detected. A required package is not available or is the wrong version for this system."
|
||||||
|
msg_warn "Hint: Run 'apt-get install -f' inside the container or check that all required repositories are configured for your distribution."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# 2. APT/GPG signature verification failure
|
||||||
|
elif echo "$_log_tail" | grep -qE "sqv|KEYEXPIRED|NO_PUBKEY|key is not certified|signature verification failed|is not signed|Sub-process.*sqv"; then
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "APT repository signature error detected."
|
||||||
|
msg_warn "Hint: A repository GPG key may be missing, expired, or the keyring file is not yet present (/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc etc.)."
|
||||||
|
msg_warn "Hint: Install the 'postgresql-common' package first, or re-add the repository with its correct signing key."
|
||||||
|
fi
|
||||||
|
# 3. Network / DNS failure during apt-get or curl
|
||||||
|
elif echo "$_log_tail" | grep -qE "Could not resolve|Failed to fetch|Unable to connect|Name or service not known|Network is unreachable|curl.*resolve"; then
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "Network or DNS failure detected."
|
||||||
|
msg_warn "Hint: Check the container's network connectivity, DNS settings, and whether any firewall or ad-blocker is intercepting traffic."
|
||||||
|
fi
|
||||||
|
# 4. APT lock held by another process
|
||||||
|
elif echo "$_log_tail" | grep -qE "Could not get lock|dpkg frontend lock|waiting for it to exit|E: Unable to lock"; then
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "APT or dpkg lock conflict detected."
|
||||||
|
msg_warn "Hint: Another package manager process may be running. Try 'rm /var/lib/dpkg/lock-frontend && dpkg --configure -a' inside the container."
|
||||||
|
fi
|
||||||
|
# 5. Disk space exhaustion
|
||||||
|
elif echo "$_log_tail" | grep -qE "No space left on device|disk quota exceeded|ENOSPC"; then
|
||||||
|
if declare -f msg_warn >/dev/null 2>&1; then
|
||||||
|
msg_warn "Disk space exhausted during installation."
|
||||||
|
msg_warn "Hint: Increase the container's disk size (pct resize <ctid> rootfs +2G) or clean up space first."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Detect context: Container (INSTALL_LOG set + inside container /root) vs Host
|
# Detect context: Container (INSTALL_LOG set + inside container /root) vs Host
|
||||||
if [[ -n "${INSTALL_LOG:-}" && -f "${INSTALL_LOG:-}" && -d /root ]]; then
|
if [[ -n "${INSTALL_LOG:-}" && -f "${INSTALL_LOG:-}" && -d /root ]]; then
|
||||||
# CONTAINER CONTEXT: Copy log and create flag file for host
|
# CONTAINER CONTEXT: Copy log and create flag file for host
|
||||||
|
|||||||
1677
misc/tools.func
1677
misc/tools.func
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ function msg_ok() {
|
|||||||
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
||||||
|
|
||||||
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||||
# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0–9.1.x
|
# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0–9.x
|
||||||
pve_check() {
|
pve_check() {
|
||||||
local PVE_VER
|
local PVE_VER
|
||||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||||
@@ -63,20 +63,14 @@ pve_check() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for Proxmox VE 9.x: allow 9.0–9.1.x
|
# Check for Proxmox VE 9.x: allow 9.0–9.x
|
||||||
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
||||||
local MINOR="${BASH_REMATCH[1]}"
|
|
||||||
if ((MINOR < 0 || MINOR > 1)); then
|
|
||||||
msg_error "This version of Proxmox VE is not yet supported."
|
|
||||||
msg_error "Supported: Proxmox VE version 9.0–9.1.x"
|
|
||||||
exit 105
|
|
||||||
fi
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# All other unsupported versions
|
# All other unsupported versions
|
||||||
msg_error "This version of Proxmox VE is not supported."
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
msg_error "Supported versions: Proxmox VE 8.0 – 8.9 or 9.0–9.1.x"
|
msg_error "Supported versions: Proxmox VE 8.0 – 8.9 or 9.0–9.x"
|
||||||
exit 105
|
exit 105
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -811,13 +811,7 @@ update_tags() {
|
|||||||
if [[ "$type" == "lxc" ]]; then
|
if [[ "$type" == "lxc" ]]; then
|
||||||
pct set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
|
pct set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
|
||||||
else
|
else
|
||||||
local vm_config="/etc/pve/qemu-server/${vmid}.conf"
|
qm set "${vmid}" --tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
|
||||||
if [[ -f "$vm_config" ]]; then
|
|
||||||
sed -i '/^tags:/d' "$vm_config"
|
|
||||||
if [[ ${#next_tags[@]} -gt 0 ]]; then
|
|
||||||
echo "tags: $(IFS=';'; echo "${next_tags[*]}")" >> "$vm_config"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
# Tags unchanged
|
# Tags unchanged
|
||||||
|
|||||||
@@ -28,7 +28,14 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-clean"
|
|||||||
|
|
||||||
# Detect current kernel
|
# Detect current kernel
|
||||||
current_kernel=$(uname -r)
|
current_kernel=$(uname -r)
|
||||||
available_kernels=$(dpkg --list | grep 'kernel-.*-pve' | awk '{print $2}' | grep -v "$current_kernel" | sort -V)
|
# Only list fully-installed (ii) versioned kernel packages; the pattern
|
||||||
|
# proxmox-kernel-X.Y.Z matches versioned kernels while excluding the
|
||||||
|
# two-segment meta-packages (proxmox-kernel-X.Y) and proxmox-kernel-helper.
|
||||||
|
available_kernels=$(dpkg --list |
|
||||||
|
awk '/^ii/ {print $2}' |
|
||||||
|
grep -E '^proxmox-kernel-[0-9]+\.[0-9]+\.[0-9]' |
|
||||||
|
grep -v "$current_kernel" |
|
||||||
|
sort -V)
|
||||||
|
|
||||||
header_info
|
header_info
|
||||||
|
|
||||||
@@ -82,10 +89,28 @@ fi
|
|||||||
# Remove kernels
|
# Remove kernels
|
||||||
for kernel in "${kernels_to_remove[@]}"; do
|
for kernel in "${kernels_to_remove[@]}"; do
|
||||||
echo -e "${YW}Removing $kernel...${CL}"
|
echo -e "${YW}Removing $kernel...${CL}"
|
||||||
if apt-get purge -y "$kernel" >/dev/null 2>&1; then
|
# Derive the major.minor meta-package name (e.g. proxmox-kernel-6.14)
|
||||||
echo -e "${GN}Successfully removed: $kernel${CL}"
|
# from a versioned name like proxmox-kernel-6.14.11-9-pve-signed.
|
||||||
|
minor_version=$(echo "$kernel" | sed -E 's/^proxmox-kernel-([0-9]+\.[0-9]+)\..*/\1/')
|
||||||
|
meta="proxmox-kernel-${minor_version}"
|
||||||
|
pkgs_to_remove=("$kernel")
|
||||||
|
# Include the meta-package in the purge when it is installed and when
|
||||||
|
# no other versioned kernel of the same minor version will remain
|
||||||
|
# (the running kernel keeps it alive if it shares the same minor).
|
||||||
|
if dpkg -l "$meta" 2>/dev/null | grep -q '^ii'; then
|
||||||
|
remaining=$(dpkg --list |
|
||||||
|
awk '/^ii/ {print $2}' |
|
||||||
|
grep -E "^proxmox-kernel-${minor_version}\." |
|
||||||
|
grep -v "^${kernel}$" |
|
||||||
|
wc -l)
|
||||||
|
if [ "$remaining" -eq 0 ]; then
|
||||||
|
pkgs_to_remove+=("$meta")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if apt-get purge -y "${pkgs_to_remove[@]}" >/dev/null 2>&1; then
|
||||||
|
echo -e "${GN}Successfully removed: ${pkgs_to_remove[*]}${CL}"
|
||||||
else
|
else
|
||||||
echo -e "${RD}Failed to remove: $kernel. Check dependencies.${CL}"
|
echo -e "${RD}Failed to remove: ${pkgs_to_remove[*]}. Check dependencies.${CL}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,19 @@ start_routines() {
|
|||||||
no) msg_error "Selected no to Backup" ;;
|
no) msg_error "Selected no to Backup" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# --- Update Current PBS 3 System ---
|
||||||
|
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PBS 3 UPDATE" --menu \
|
||||||
|
"\nUpdate current PBS 3 (Bookworm) packages before upgrade?" 14 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
|
||||||
|
case $CHOICE in
|
||||||
|
yes)
|
||||||
|
msg_info "Updating current PBS 3 packages"
|
||||||
|
apt-get update
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
|
||||||
|
msg_ok "Updated current PBS 3 packages"
|
||||||
|
;;
|
||||||
|
no) msg_error "Skipped updating current packages" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
# --- Debian 13 Sources ---
|
# --- Debian 13 Sources ---
|
||||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PBS 4 SOURCES" --menu \
|
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PBS 4 SOURCES" --menu \
|
||||||
"Switch to Debian 13 (Trixie) sources for PBS 4?" 14 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
|
"Switch to Debian 13 (Trixie) sources for PBS 4?" 14 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
|
||||||
|
|||||||
Reference in New Issue
Block a user