Compare commits

...

44 Commits

Author SHA1 Message Date
GitHub Actions
cc4961a358 Update .app files 2026-02-24 10:54:21 +00:00
CanbiZ (MickLesk)
83f03d617e Refactor n8n (#12264) 2026-02-24 11:54:02 +01:00
community-scripts-pr-app[bot]
4c5d5b2030 Update CHANGELOG.md (#12272)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 10:38:42 +00:00
CanbiZ (MickLesk)
4e1ade4c28 bump various scripts from Node 22 to 24 (#12265)
* bump(node): Node 22 to 24 for Tier 1 projects

Bump Node.js from 22 to 24 in install and ct update scripts for projects
where upstream already uses Node 24 in their Dockerfile/package.json:

- Cross-seed (engines >=24, Dockerfile node:24-alpine)
- Matterbridge (engines >=24.0.0, Dockerfile node:24-trixie-slim)
- Manyfold (volta.node 24.13.0)
- Pangolin (Dockerfile node:24-alpine)
- ROMM (engines 24, nvm install 24)
- SnowShare (Dockerfile node:24-alpine)
- Verdaccio (engines >=18, Dockerfile node:24-alpine)

Also adds missing NODE_VERSION setup_nodejs calls to ct update scripts
for cross-seed, pangolin, romm, snowshare, and manyfold.

* formatting

* fix: pin NODE_VERSION for nodecast-tv and wealthfolio

nodecast-tv: NODE_VERSION=20 (upstream Dockerfile uses nodesource/setup_20.x)
wealthfolio: NODE_VERSION=20 (upstream Dockerfile uses node:20-alpine)

* ci: add weekly Node.js version drift check workflow

Scans all install scripts using setup_nodejs, fetches upstream
package.json (engines.node) and Dockerfile (FROM node:XX),
compares with our NODE_VERSION and opens/updates a GitHub issue
on mismatch. Runs weekly on Monday at 06:00 UTC.

* remove wf - seperate branch
2026-02-24 11:38:15 +01:00
community-scripts-pr-app[bot]
e5073d1a4f Update CHANGELOG.md (#12270)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 10:35:32 +00:00
community-scripts-pr-app[bot]
01e956bdf8 Update CHANGELOG.md (#12269)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 10:35:01 +00:00
community-scripts-pr-app[bot]
0cc049edb6 Update date in json (#12268)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-24 10:34:55 +00:00
push-app-to-main[bot]
ffa1a26b5e Arcane (#12263)
* Add arcane (addon)

* Update tools/addon/arcane.sh

Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-02-24 11:34:33 +01:00
community-scripts-pr-app[bot]
59ca9c26c9 Update CHANGELOG.md (#12266)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 10:08:03 +00:00
CanbiZ (MickLesk)
56de2d1e39 feat(tools): add get_latest_gh_tag helper function (#12261)
Adds a reusable function to fetch the latest tag from a GitHub repo.
Useful for projects that only use tags, not full releases (e.g.
mongodb/mongo-tools).

Features:
- Optional prefix filter (e.g. '100.' or 'v')
- Optional prefix stripping for clean version output
- Skips pre-release tags (rc, alpha, beta, dev, test)
- Sorts by version (sort -V) to find the latest
- Respects GITHUB_TOKEN for rate limiting
2026-02-24 11:07:40 +01:00
community-scripts-pr-app[bot]
72eb8b9575 Update CHANGELOG.md (#12262)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 08:41:34 +00:00
Tobias
65a67347bd Create stale_pr_close.yml (#12243) 2026-02-24 09:41:06 +01:00
community-scripts-pr-app[bot]
25d54ff69a Update CHANGELOG.md (#12260)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 08:25:15 +00:00
D12R
5c85c5098e adds further documentation during the installation script. (#12248) 2026-02-24 09:24:44 +01:00
community-scripts-pr-app[bot]
7b8080438d Update CHANGELOG.md (#12258)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 08:09:46 +00:00
community-scripts-pr-app[bot]
2041371a04 Update CHANGELOG.md (#12257)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 08:09:19 +00:00
Stefan Tomas
b172301e0f Fix/make searxng updateable (#12207)
* Made update script useable

* Added info messages

* Use $STD prefix for all update commands

* Update ct/searxng.sh

Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>

* Update searxng.sh

---------

Co-authored-by: Stefan Tomas <stefan.tomas@proton.me>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-02-24 09:08:56 +01:00
community-scripts-pr-app[bot]
4b6cb1601b Update CHANGELOG.md (#12256)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 07:32:38 +00:00
Slaviša Arežina
d9f766cca6 PHP bump (#12247) 2026-02-24 08:32:11 +01:00
community-scripts-pr-app[bot]
a4973fa3b7 chore: update github-versions.json (#12254)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 06:23:48 +00:00
community-scripts-pr-app[bot]
dcbb8490f1 Update CHANGELOG.md (#12252)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 00:23:06 +00:00
community-scripts-pr-app[bot]
3aa5431302 chore: update github-versions.json (#12251)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-24 00:22:45 +00:00
community-scripts-pr-app[bot]
2e753578cd Update .app files (#12239)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 22:44:05 +01:00
community-scripts-pr-app[bot]
483ead9a8b Update CHANGELOG.md (#12242)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 21:42:28 +00:00
community-scripts-pr-app[bot]
53ee9403cd Update CHANGELOG.md (#12241)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 21:42:04 +00:00
community-scripts-pr-app[bot]
ed7e71f8c3 Update date in json (#12240)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 21:42:00 +00:00
push-app-to-main[bot]
97d4b3ffc2 SeaweedFS (#12220)
* Add seaweedfs (ct)

* Update seaweedfs.sh

* Add var_fuse variable with default value 'yes'

* Formatting

* Update seaweedfs-install.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: tremor021 <arezina.slavisa@gmail.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-02-23 22:41:29 +01:00
community-scripts-pr-app[bot]
e226386c9d Update .app files (#12233)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 19:43:54 +01:00
community-scripts-pr-app[bot]
4e7e348322 Update CHANGELOG.md (#12237)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 18:26:44 +00:00
community-scripts-pr-app[bot]
0920d56218 chore: update github-versions.json (#12236)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 18:26:16 +00:00
community-scripts-pr-app[bot]
071420c39a Update CHANGELOG.md (#12235)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 18:22:14 +00:00
community-scripts-pr-app[bot]
6a7bc481a4 Update CHANGELOG.md (#12234)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 18:22:00 +00:00
community-scripts-pr-app[bot]
11fb4743cc Update date in json (#12232)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 18:21:45 +00:00
push-app-to-main[bot]
b2a710e673 Sonobarr (#12221)
* Add sonobarr (ct)

* Update script source URL for build function

* Change default var_tags from 'storage' to 'music;discovery'

* Formatting

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Chris <punk.sand7393@fastmail.com>
Co-authored-by: tremor021 <arezina.slavisa@gmail.com>
2026-02-23 19:21:26 +01:00
community-scripts-pr-app[bot]
49f1f16cba Update CHANGELOG.md (#12229)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 17:38:17 +00:00
CanbiZ (MickLesk)
8005ddd74f memos: unpin version due new release artifacts (#12224) 2026-02-23 18:37:27 +01:00
community-scripts-pr-app[bot]
2fead98966 Update CHANGELOG.md (#12228)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 17:26:00 +00:00
Michel Roegl-Brunner
09de4e9ca9 Remove huntarr (#12226)
* huntarr.sh

* huntarr-install.sh löschen

* Delete frontend/public/json/huntarr.json

* Delete ct/headers/huntarr

---------

Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-02-23 18:25:24 +01:00
community-scripts-pr-app[bot]
e1815642b2 Update CHANGELOG.md (#12227)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 17:25:00 +00:00
CanbiZ (MickLesk)
75da6920d5 booklore v2: embed frontend, bump Java to 25, remove nginx (#12223) 2026-02-23 18:24:33 +01:00
CanbiZ (MickLesk)
5f13d29c57 fix(telemetry): prevent sporadic stuck 'configuring' status on success
Root cause: post_update_to_api set POST_UPDATE_DONE=true even after
all 3 retry attempts failed (curl timeout, API error). This prevented
the EXIT trap (api_exit_script) from retrying with fresh attempts.

Changes:
- Only set POST_UPDATE_DONE=true on actual HTTP 2xx success
- If all 3 attempts fail, EXIT trap gets 3 more fresh attempts
- Increase timeout from 5s to 10s for final status updates (STATUS_TIMEOUT)
  Progress pings keep 5s (TELEMETRY_TIMEOUT) since they're lightweight
- post_update_to_api_extended: add proper retry logic + HTTP code check
  (was fire-and-forget with no retry)
2026-02-23 17:24:06 +01:00
CanbiZ (MickLesk)
3c83654666 fix(telemetry): move 'configuring' transition to right after container creation
Validation status was persisting through container start, network check,
and OS customization. Now transitions to 'configuring' immediately after
create_lxc_container returns. Validation only covers storage/template/cluster
checks as intended.
2026-02-23 17:11:14 +01:00
CanbiZ (MickLesk)
ae3a249854 Capture lxc-attach output to host log
Pipe lxc-attach output through tee into /tmp/.install-capture-${SESSION_ID}.log and use PIPESTATUS[0] to get the real lxc-attach exit code. Prefer a pulled container-side INSTALL_LOG when it exists and is >100 bytes; otherwise fall back to the host-captured terminal log (stripping ANSI codes) and append it to the combined log so get_full_log() can find it. Apply the same capture behavior to the retry path and remove temporary capture files on completion. This makes install output reliable when container-side logging is missing (DNS errors, early crashes, or missing silent() usage).
2026-02-23 17:08:38 +01:00
CanbiZ (MickLesk)
a8a1cbcf3e feat(telemetry): add 'validation' status, fix status transitions, show 20 log lines
Status flow is now: installing → validation → configuring → success/failed

Changes:
- post_progress_to_api() accepts optional status parameter (default: configuring)
- build.func: Send 'validation' before storage/template/cluster checks
- build.func: Send 'configuring' just before lxc-attach (app install)
- build.func: Remove redundant progress pings during container start/network
- install.func + alpine-install.func: Accept status parameter in container-side
  post_progress_to_api()
- core.func + vm-core.func: silent() now shows last 20 lines on error (was 10)
2026-02-23 17:01:18 +01:00
51 changed files with 1102 additions and 305 deletions

111
.github/workflows/stale_pr_close.yml generated vendored Normal file
View File

@@ -0,0 +1,111 @@
name: Stale PR Management
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
pull_request_target:
types:
- labeled
jobs:
stale-prs:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
contents: read
steps:
- name: Handle stale PRs
uses: actions/github-script@v7
with:
script: |
const now = new Date();
const owner = context.repo.owner;
const repo = context.repo.repo;
// --- When stale label is added, comment immediately ---
if (context.eventName === "pull_request_target" && context.payload.action === "labeled") {
const label = context.payload.label?.name;
if (label === "stale") {
const author = context.payload.pull_request.user.login;
await github.rest.issues.createComment({
owner,
repo,
issue_number: context.payload.pull_request.number,
body: `@${author} This PR has been marked as stale. It will be closed if no new commits are added in 7 days.`
});
}
return;
}
// --- Scheduled run: check all stale PRs ---
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
state: "open",
per_page: 100
});
for (const pr of prs) {
const hasStale = pr.labels.some(l => l.name === "stale");
if (!hasStale) continue;
// Get timeline events to find when stale label was added
const { data: events } = await github.rest.issues.listEvents({
owner,
repo,
issue_number: pr.number,
per_page: 100
});
// Find the most recent time the stale label was added
const staleLabelEvents = events
.filter(e => e.event === "labeled" && e.label?.name === "stale")
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
if (staleLabelEvents.length === 0) continue;
const staleLabelDate = new Date(staleLabelEvents[0].created_at);
const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24);
// Check for new commits since stale label was added
const { data: commits } = await github.rest.pulls.listCommits({
owner,
repo,
pull_number: pr.number
});
const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date);
const author = pr.user.login;
// If there are new commits after the stale label, remove it
if (lastCommitDate > staleLabelDate) {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: pr.number,
name: "stale"
});
await github.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body: `@${author} Recent activity detected. Removing stale label.`
});
}
// If 7 days have passed since stale label, close the PR
else if (daysSinceStale > 7) {
await github.rest.pulls.update({
owner,
repo,
pull_number: pr.number,
state: "closed"
});
await github.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body: `@${author} Closing stale PR due to inactivity (no commits for 7 days after stale label).`
});
}
}

View File

@@ -407,19 +407,62 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-02-24
### 🚀 Updated Scripts
- adds further documentation during the installation script. [@d12rio](https://github.com/d12rio) ([#12248](https://github.com/community-scripts/ProxmoxVE/pull/12248))
- #### 🐞 Bug Fixes
- Firefly: PHP bump [@tremor021](https://github.com/tremor021) ([#12247](https://github.com/community-scripts/ProxmoxVE/pull/12247))
- #### ✨ New Features
- make searxng updateable [@shtefko](https://github.com/shtefko) ([#12207](https://github.com/community-scripts/ProxmoxVE/pull/12207))
- #### 🔧 Refactor
- bump various scripts from Node 22 to 24 [@MickLesk](https://github.com/MickLesk) ([#12265](https://github.com/community-scripts/ProxmoxVE/pull/12265))
### 💾 Core
- #### ✨ New Features
- tools.func: add get_latest_gh_tag helper function [@MickLesk](https://github.com/MickLesk) ([#12261](https://github.com/community-scripts/ProxmoxVE/pull/12261))
### 🧰 Tools
- Arcane ([#12263](https://github.com/community-scripts/ProxmoxVE/pull/12263))
### 📂 Github
- add: workflow to close stale PRs [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12243](https://github.com/community-scripts/ProxmoxVE/pull/12243))
## 2026-02-23
### 🆕 New Scripts
- SparkyFitness ([#12185](https://github.com/community-scripts/ProxmoxVE/pull/12185))
- SeaweedFS ([#12220](https://github.com/community-scripts/ProxmoxVE/pull/12220))
- Sonobarr ([#12221](https://github.com/community-scripts/ProxmoxVE/pull/12221))
- SparkyFitness ([#12185](https://github.com/community-scripts/ProxmoxVE/pull/12185))
- Frigate v16.4 [@MickLesk](https://github.com/MickLesk) ([#11887](https://github.com/community-scripts/ProxmoxVE/pull/11887))
### 🚀 Updated Scripts
- #### ✨ New Features
- memos: unpin version due new release artifacts [@MickLesk](https://github.com/MickLesk) ([#12224](https://github.com/community-scripts/ProxmoxVE/pull/12224))
- core: Enhance signal handling, reported "status" and logs [@MickLesk](https://github.com/MickLesk) ([#12216](https://github.com/community-scripts/ProxmoxVE/pull/12216))
- #### 🔧 Refactor
- booklore v2: embed frontend, bump Java to 25, remove nginx [@MickLesk](https://github.com/MickLesk) ([#12223](https://github.com/community-scripts/ProxmoxVE/pull/12223))
### 🗑️ Deleted Scripts
- Remove: Huntarr (deprecated & Security) [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#12226](https://github.com/community-scripts/ProxmoxVE/pull/12226))
### 💾 Core
- #### 🔧 Refactor

View File

@@ -30,7 +30,7 @@ function update_script() {
fi
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
JAVA_VERSION="21" setup_java
JAVA_VERSION="25" setup_java
NODE_VERSION="22" setup_nodejs
setup_mariadb
setup_yq
@@ -60,11 +60,16 @@ function update_script() {
$STD npm run build --configuration=production
msg_ok "Built Frontend"
msg_info "Embedding Frontend into Backend"
mkdir -p /opt/booklore/booklore-api/src/main/resources/static
cp -r /opt/booklore/booklore-ui/dist/booklore/browser/* /opt/booklore/booklore-api/src/main/resources/static/
msg_ok "Embedded Frontend into Backend"
msg_info "Building Backend"
cd /opt/booklore/booklore-api
APP_VERSION=$(get_latest_github_release "booklore-app/BookLore")
yq eval ".app.version = \"${APP_VERSION}\"" -i src/main/resources/application.yaml
$STD ./gradlew clean build --no-daemon
$STD ./gradlew clean build -x test --no-daemon
mkdir -p /opt/booklore/dist
JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1)
if [[ -z "$JAR_PATH" ]]; then
@@ -74,9 +79,22 @@ function update_script() {
cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend"
if systemctl is-active --quiet nginx 2>/dev/null; then
msg_info "Removing Nginx (no longer needed)"
systemctl disable --now nginx
$STD apt-get purge -y nginx nginx-common
msg_ok "Removed Nginx"
fi
if ! grep -q "^SERVER_PORT=" /opt/booklore_storage/.env 2>/dev/null; then
echo "SERVER_PORT=6060" >>/opt/booklore_storage/.env
fi
sed -i 's|ExecStart=/usr/bin/java -jar|ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -jar|' /etc/systemd/system/booklore.service
systemctl daemon-reload
msg_info "Starting Service"
systemctl start booklore
systemctl reload nginx
rm -rf /opt/booklore_bak
msg_ok "Started Service"
msg_ok "Updated successfully!"

View File

@@ -20,26 +20,28 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
header_info
check_container_storage
check_container_resources
if command -v cross-seed &>/dev/null; then
current_version=$(cross-seed --version)
latest_version=$(npm show cross-seed version)
if [ "$current_version" != "$latest_version" ]; then
msg_info "Updating cross-seed from version v${current_version} to v${latest_version}"
$STD npm install -g cross-seed@latest
systemctl restart cross-seed
msg_ok "Updated successfully!"
else
msg_ok "cross-seed is already at v${current_version}"
fi
NODE_VERSION="24" setup_nodejs
if command -v cross-seed &>/dev/null; then
current_version=$(cross-seed --version)
latest_version=$(npm show cross-seed version)
if [ "$current_version" != "$latest_version" ]; then
msg_info "Updating cross-seed from version v${current_version} to v${latest_version}"
$STD npm install -g cross-seed@latest
systemctl restart cross-seed
msg_ok "Updated successfully!"
else
msg_error "No cross-seed Installation Found!"
exit
msg_ok "cross-seed is already at v${current_version}"
fi
else
msg_error "No cross-seed Installation Found!"
exit
fi
exit
}
start

View File

@@ -28,7 +28,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
setup_mariadb
PHP_VERSION="8.5" PHP_APACHE="YES" setup_php
if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then
systemctl stop apache2
cp /opt/firefly/.env /opt/.env

View File

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

6
ct/headers/seaweedfs Normal file
View File

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

6
ct/headers/sonobarr Normal file
View File

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

View File

@@ -28,6 +28,8 @@ function update_script() {
exit
fi
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
if check_for_gh_release "manyfold" "manyfold3d/manyfold"; then
msg_info "Stopping Services"
systemctl stop manyfold.target manyfold-rails.1 manyfold-default_worker.1 manyfold-performance_worker.1

View File

@@ -29,7 +29,7 @@ function update_script() {
fi
$STD apt update
$STD apt upgrade -y
NODE_VERSION="22" NODE_MODULE="matterbridge" setup_nodejs
NODE_VERSION="24" NODE_MODULE="matterbridge" setup_nodejs
msg_ok "Updated successfully!"
exit
}

View File

@@ -27,12 +27,12 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "memos" "usememos/memos" "v0.25.3"; then
if check_for_gh_release "memos" "usememos/memos"; then
msg_info "Stopping service"
systemctl stop memos
msg_ok "Service stopped"
fetch_and_deploy_gh_release "memos" "usememos/memos" "prebuild" "v0.25.3" "/opt/memos" "memos*linux_amd64.tar.gz"
fetch_and_deploy_gh_release "memos" "usememos/memos" "prebuild" "latest" "/opt/memos" "memos*linux_amd64.tar.gz"
msg_info "Starting service"
systemctl start memos

View File

@@ -27,7 +27,11 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
ensure_dependencies graphicsmagick
ensure_dependencies graphicsmagick
NODE_VERSION="24" setup_nodejs
msg_info "Updating n8n"
if [ ! -f /opt/n8n.env ]; then
sed -i 's|^Environment="N8N_SECURE_COOKIE=false"$|EnvironmentFile=/opt/n8n.env|' /etc/systemd/system/n8n.service
mkdir -p /opt
@@ -37,14 +41,12 @@ N8N_PORT=5678
N8N_PROTOCOL=http
N8N_HOST=$LOCAL_IP
EOF
systemctl daemon-reload
fi
NODE_VERSION="22" setup_nodejs
msg_info "Updating ${APP} LXC"
rm -rf /usr/lib/node_modules/.n8n-* /usr/lib/node_modules/n8n
$STD npm install -g n8n --force
$STD npm update -g n8n
systemctl restart n8n
msg_ok "Updated n8n"
msg_ok "Updated successfully!"
exit
}

View File

@@ -29,6 +29,8 @@ function update_script() {
exit
fi
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "pangolin" "fosrl/pangolin"; then
msg_info "Stopping Service"
systemctl stop pangolin

View File

@@ -20,48 +20,50 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/romm ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "romm" "rommapp/romm"; then
msg_info "Stopping Services"
systemctl stop romm-backend romm-worker romm-scheduler romm-watcher
msg_ok "Stopped Services"
msg_info "Backing up configuration"
cp /opt/romm/.env /opt/romm/.env.backup
msg_ok "Backed up configuration"
fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm"
msg_info "Updating ROMM"
cp /opt/romm/.env.backup /opt/romm/.env
cd /opt/romm
$STD uv sync --all-extras
cd /opt/romm/backend
$STD uv run alembic upgrade head
cd /opt/romm/frontend
$STD npm install
$STD npm run build
# Merge static assets into dist folder
cp -rf /opt/romm/frontend/assets/* /opt/romm/frontend/dist/assets/
mkdir -p /opt/romm/frontend/dist/assets/romm
ln -sfn /var/lib/romm/resources /opt/romm/frontend/dist/assets/romm/resources
ln -sfn /var/lib/romm/assets /opt/romm/frontend/dist/assets/romm/assets
msg_ok "Updated ROMM"
msg_info "Starting Services"
systemctl start romm-backend romm-worker romm-scheduler romm-watcher
msg_ok "Started Services"
msg_ok "Updated successfully"
fi
if [[ ! -d /opt/romm ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "romm" "rommapp/romm"; then
msg_info "Stopping Services"
systemctl stop romm-backend romm-worker romm-scheduler romm-watcher
msg_ok "Stopped Services"
msg_info "Backing up configuration"
cp /opt/romm/.env /opt/romm/.env.backup
msg_ok "Backed up configuration"
fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm"
msg_info "Updating ROMM"
cp /opt/romm/.env.backup /opt/romm/.env
cd /opt/romm
$STD uv sync --all-extras
cd /opt/romm/backend
$STD uv run alembic upgrade head
cd /opt/romm/frontend
$STD npm install
$STD npm run build
# Merge static assets into dist folder
cp -rf /opt/romm/frontend/assets/* /opt/romm/frontend/dist/assets/
mkdir -p /opt/romm/frontend/dist/assets/romm
ln -sfn /var/lib/romm/resources /opt/romm/frontend/dist/assets/romm/resources
ln -sfn /var/lib/romm/assets /opt/romm/frontend/dist/assets/romm/assets
msg_ok "Updated ROMM"
msg_info "Starting Services"
systemctl start romm-backend romm-worker romm-scheduler romm-watcher
msg_ok "Started Services"
msg_ok "Updated successfully"
fi
exit
}
start

View File

@@ -27,12 +27,33 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_ok "There is currently no update available."
# sed -i 's/^\([[:space:]]*limiter:\)[[:space:]]*true/\1 false/' /etc/searxng/settings.yml
# if cd /usr/local/searxng/searxng-src && git pull | grep -q 'Already up to date'; then
# msg_ok "There is currently no update available."
# fi
exit
chown -R searxng:searxng /usr/local/searxng/searxng-src
if su -s /bin/bash -c "git -C /usr/local/searxng/searxng-src pull" searxng | grep -q 'Already up to date'; then
msg_ok "There is currently no update available."
exit
fi
msg_info "Updating SearXNG installation"
msg_info "Stopping Service"
systemctl stop searxng
msg_ok "Stopped Service"
msg_info "Updating SearXNG"
$STD su -s /bin/bash searxng -c '
python3 -m venv /usr/local/searxng/searx-pyenv &&
. /usr/local/searxng/searx-pyenv/bin/activate &&
pip install -U pip setuptools wheel pyyaml lxml msgspec typing_extensions &&
pip install --use-pep517 --no-build-isolation -e /usr/local/searxng/searxng-src
'
msg_ok "Updated SearXNG"
msg_info "Starting Services"
systemctl start searxng
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container

View File

@@ -1,18 +1,19 @@
#!/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: BiluliB
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/plexguide/Huntarr.io
# Source: https://github.com/seaweedfs/seaweedfs
APP="huntarr"
var_tags="${var_tags:-arr}"
APP="SeaweedFS"
var_tags="${var_tags:-storage;s3;filesystem}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-16}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
var_fuse="${var_fuse:-yes}"
header_info "$APP"
variables
@@ -24,28 +25,20 @@ function update_script() {
check_container_storage
check_container_resources
if [[ ! -f /opt/huntarr/main.py ]]; then
if [[ ! -f /opt/seaweedfs/weed ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
PYTHON_VERSION="3.12" setup_uv
if check_for_gh_release "huntarr" "plexguide/Huntarr.io"; then
if check_for_gh_release "seaweedfs" "seaweedfs/seaweedfs"; then
msg_info "Stopping Service"
systemctl stop huntarr
systemctl stop seaweedfs
msg_ok "Stopped Service"
ensure_dependencies build-essential
fetch_and_deploy_gh_release "huntarr" "plexguide/Huntarr.io" "tarball"
msg_info "Updating Huntarr"
cd /opt/huntarr
$STD uv pip install -r requirements.txt --python /opt/huntarr/.venv/bin/python
msg_ok "Updated Huntarr"
fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest" "/opt/seaweedfs" "linux_amd64.tar.gz"
msg_info "Starting Service"
systemctl start huntarr
systemctl start seaweedfs
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
@@ -56,7 +49,7 @@ start
build_container
description
msg_ok "Completed successfully!\n"
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}:9705${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9333${CL}"

View File

@@ -28,6 +28,8 @@ function update_script() {
exit
fi
NODE_VERSION="24" setup_nodejs
if check_for_gh_release "snowshare" "TuroYT/snowshare"; then
msg_info "Stopping Service"
systemctl stop snowshare

63
ct/sonobarr.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/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: GoldenSpringness
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Dodelidoo-Labs/sonobarr
APP="sonobarr"
var_tags="${var_tags:-music;discovery}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d "/opt/sonobarr" ]]; then
msg_error "No sonobarr Installation Found!"
exit
fi
PYTHON_VERSION="3.12" setup_uv
if check_for_gh_release "sonobarr" "Dodelidoo-Labs/sonobarr"; then
msg_info "Stopping Service"
systemctl stop sonobarr
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sonobarr" "Dodelidoo-Labs/sonobarr" "tarball"
msg_info "Updating sonobarr"
$STD uv venv -c /opt/sonobarr/venv
$STD source /opt/sonobarr/venv/bin/activate
$STD uv pip install --no-cache-dir -r /opt/sonobarr/requirements.txt
sed -i "/release_version/s/=.*/=$(cat ~/.sonobarr)/" /etc/sonobarr/.env
msg_ok "Updated sonobarr"
msg_info "Starting Service"
systemctl start sonobarr
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}sonobarr setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5000${CL}"

View File

@@ -33,7 +33,7 @@ function update_script() {
$STD apt upgrade -y
msg_ok "Updated LXC Container"
NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
NODE_VERSION="24" NODE_MODULE="verdaccio" setup_nodejs
systemctl restart verdaccio
msg_ok "Updated successfully!"
exit

View File

@@ -0,0 +1,40 @@
{
"name": "Arcane",
"slug": "arcane",
"categories": [
3
],
"date_created": "2026-02-24",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 3552,
"documentation": "https://getarcane.app/docs",
"website": "https://getarcane.app/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/arcane.webp",
"config_path": "/opt/arcane/.env",
"description": "Arcane is designed to be an easy and modern Docker management platform, built with everybody in mind. The goal of Arcane is to be built for and by the community to make sure nobody feels left out or behind with their specific features or processes. ",
"install_methods": [
{
"type": "default",
"script": "tools/addon/arcane.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": "arcane",
"password": "arcane-admin"
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
}
]
}

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-02-23T12:14:19Z",
"generated": "2026-02-24T06:23:39Z",
"versions": [
{
"slug": "2fauth",
@@ -25,9 +25,9 @@
{
"slug": "adventurelog",
"repo": "seanmorley15/adventurelog",
"version": "v0.11.0",
"version": "v0.12.0",
"pinned": false,
"date": "2025-09-01T16:19:38Z"
"date": "2026-02-23T14:06:45Z"
},
{
"slug": "alpine-redlib",
@@ -151,9 +151,9 @@
{
"slug": "booklore",
"repo": "booklore-app/BookLore",
"version": "v1.18.5",
"version": "v2.0.1",
"pinned": false,
"date": "2026-01-24T17:15:32Z"
"date": "2026-02-24T04:15:33Z"
},
{
"slug": "bookstack",
@@ -200,9 +200,9 @@
{
"slug": "cleanuparr",
"repo": "Cleanuparr/Cleanuparr",
"version": "v2.7.1",
"version": "v2.7.4",
"pinned": false,
"date": "2026-02-23T09:58:13Z"
"date": "2026-02-23T18:41:16Z"
},
{
"slug": "cloudreve",
@@ -228,9 +228,9 @@
{
"slug": "configarr",
"repo": "raydak-labs/configarr",
"version": "v1.22.0",
"version": "v1.23.0",
"pinned": false,
"date": "2026-02-20T21:55:46Z"
"date": "2026-02-23T12:28:13Z"
},
{
"slug": "convertx",
@@ -249,9 +249,9 @@
{
"slug": "cronicle",
"repo": "jhuckaby/Cronicle",
"version": "v0.9.106",
"version": "v0.9.107",
"pinned": false,
"date": "2026-02-11T17:11:46Z"
"date": "2026-02-23T17:48:27Z"
},
{
"slug": "cronmaster",
@@ -382,9 +382,9 @@
{
"slug": "firefly",
"repo": "firefly-iii/firefly-iii",
"version": "v6.4.23",
"version": "v6.5.0",
"pinned": false,
"date": "2026-02-20T07:02:05Z"
"date": "2026-02-23T19:19:00Z"
},
{
"slug": "fladder",
@@ -438,9 +438,9 @@
{
"slug": "ghostfolio",
"repo": "ghostfolio/ghostfolio",
"version": "2.242.0",
"version": "2.243.0",
"pinned": false,
"date": "2026-02-22T10:01:44Z"
"date": "2026-02-23T19:31:36Z"
},
{
"slug": "gitea",
@@ -452,9 +452,9 @@
{
"slug": "gitea-mirror",
"repo": "RayLabsHQ/gitea-mirror",
"version": "v3.9.2",
"version": "v3.9.4",
"pinned": false,
"date": "2025-11-08T05:36:48Z"
"date": "2026-02-24T06:17:56Z"
},
{
"slug": "glance",
@@ -582,13 +582,6 @@
"pinned": false,
"date": "2025-12-23T14:53:51Z"
},
{
"slug": "huntarr",
"repo": "plexguide/Huntarr.io",
"version": "9.4.1",
"pinned": false,
"date": "2026-02-23T08:46:37Z"
},
{
"slug": "immich-public-proxy",
"repo": "alangrainger/immich-public-proxy",
@@ -620,9 +613,9 @@
{
"slug": "jackett",
"repo": "Jackett/Jackett",
"version": "v0.24.1184",
"version": "v0.24.1193",
"pinned": false,
"date": "2026-02-23T05:55:36Z"
"date": "2026-02-24T05:58:04Z"
},
{
"slug": "jellystat",
@@ -865,9 +858,9 @@
{
"slug": "memos",
"repo": "usememos/memos",
"version": "v0.25.3",
"pinned": true,
"date": "2025-11-25T15:40:41Z"
"version": "v0.26.2",
"pinned": false,
"date": "2026-02-23T13:28:34Z"
},
{
"slug": "metube",
@@ -1124,9 +1117,9 @@
{
"slug": "planka",
"repo": "plankanban/planka",
"version": "v2.0.1",
"version": "v2.0.2",
"pinned": false,
"date": "2026-02-17T15:26:55Z"
"date": "2026-02-23T17:47:15Z"
},
{
"slug": "plant-it",
@@ -1145,9 +1138,9 @@
{
"slug": "pocketid",
"repo": "pocket-id/pocket-id",
"version": "v2.2.0",
"version": "v2.3.0",
"pinned": false,
"date": "2026-01-11T15:01:07Z"
"date": "2026-02-23T19:50:48Z"
},
{
"slug": "privatebin",
@@ -1250,9 +1243,9 @@
{
"slug": "qui",
"repo": "autobrr/qui",
"version": "v1.14.0",
"version": "v1.14.1",
"pinned": false,
"date": "2026-02-21T22:23:46Z"
"date": "2026-02-23T13:13:31Z"
},
{
"slug": "radarr",
@@ -1278,9 +1271,9 @@
{
"slug": "rdtclient",
"repo": "rogerfar/rdt-client",
"version": "v2.0.123",
"version": "v2.0.124",
"pinned": false,
"date": "2026-02-21T23:08:13Z"
"date": "2026-02-24T03:18:03Z"
},
{
"slug": "reactive-resume",
@@ -1352,6 +1345,13 @@
"pinned": false,
"date": "2026-02-12T14:20:56Z"
},
{
"slug": "seaweedfs",
"repo": "seaweedfs/seaweedfs",
"version": "4.13",
"pinned": false,
"date": "2026-02-17T01:09:45Z"
},
{
"slug": "seelf",
"repo": "YuukanOO/seelf",
@@ -1404,16 +1404,16 @@
{
"slug": "snipeit",
"repo": "grokability/snipe-it",
"version": "v8.3.7",
"version": "v8.4.0",
"pinned": false,
"date": "2025-12-12T09:13:40Z"
"date": "2026-02-23T20:59:43Z"
},
{
"slug": "snowshare",
"repo": "TuroYT/snowshare",
"version": "v1.3.6",
"version": "v1.3.7",
"pinned": false,
"date": "2026-02-19T11:06:29Z"
"date": "2026-02-23T15:51:39Z"
},
{
"slug": "sonarr",
@@ -1422,6 +1422,13 @@
"pinned": false,
"date": "2025-11-05T01:56:48Z"
},
{
"slug": "sonobarr",
"repo": "Dodelidoo-Labs/sonobarr",
"version": "0.11.0",
"pinned": false,
"date": "2026-01-21T19:07:21Z"
},
{
"slug": "speedtest-tracker",
"repo": "alexjustesen/speedtest-tracker",
@@ -1446,9 +1453,9 @@
{
"slug": "stirling-pdf",
"repo": "Stirling-Tools/Stirling-PDF",
"version": "v2.5.2",
"version": "v2.5.3",
"pinned": false,
"date": "2026-02-20T23:20:20Z"
"date": "2026-02-23T23:23:39Z"
},
{
"slug": "streamlink-webui",
@@ -1558,9 +1565,9 @@
{
"slug": "traefik",
"repo": "traefik/traefik",
"version": "v3.6.8",
"version": "v3.6.9",
"pinned": false,
"date": "2026-02-11T16:44:37Z"
"date": "2026-02-23T17:21:17Z"
},
{
"slug": "trilium",
@@ -1572,9 +1579,9 @@
{
"slug": "trip",
"repo": "itskovacs/TRIP",
"version": "1.40.0",
"version": "1.41.0",
"pinned": false,
"date": "2026-02-10T20:12:53Z"
"date": "2026-02-23T17:57:31Z"
},
{
"slug": "tududi",
@@ -1586,9 +1593,9 @@
{
"slug": "tunarr",
"repo": "chrisbenincasa/tunarr",
"version": "v1.1.15",
"version": "v1.1.16",
"pinned": false,
"date": "2026-02-19T23:51:17Z"
"date": "2026-02-23T21:24:47Z"
},
{
"slug": "uhf",
@@ -1635,9 +1642,9 @@
{
"slug": "vaultwarden",
"repo": "dani-garcia/vaultwarden",
"version": "1.35.3",
"version": "1.35.4",
"pinned": false,
"date": "2026-02-10T20:37:03Z"
"date": "2026-02-23T21:43:25Z"
},
{
"slug": "victoriametrics",
@@ -1733,16 +1740,16 @@
{
"slug": "wishlist",
"repo": "cmintey/wishlist",
"version": "v0.60.0",
"version": "v0.60.1",
"pinned": false,
"date": "2026-02-10T04:05:26Z"
"date": "2026-02-24T04:01:37Z"
},
{
"slug": "wizarr",
"repo": "wizarrrr/wizarr",
"version": "v2025.12.0",
"version": "v2026.2.0",
"pinned": false,
"date": "2025-12-09T14:30:23Z"
"date": "2026-02-23T19:25:28Z"
},
{
"slug": "writefreely",

View File

@@ -1,36 +0,0 @@
{
"name": "Huntarr",
"slug": "huntarr",
"categories": [
14
],
"date_created": "2025-06-18",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9705,
"documentation": "https://github.com/plexguide/Huntarr.io/wiki",
"config_path": "/opt/huntarr",
"website": "https://github.com/plexguide/Huntarr.io",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/huntarr.webp",
"description": "Huntarr is a tool that automates the search for missing or low-quality media content in your collection. It works seamlessly with applications like Sonarr, Radarr, Lidarr, Readarr, and Whisparr, enhancing their functionality with continuous background scans to identify and update missed or outdated content. Through a user-friendly web interface accessible on port 9705, Huntarr provides real-time statistics, log views, and extensive configuration options. The software is especially useful for users who want to keep their media library up to date by automatically searching for missing episodes or higher-quality versions. Huntarr is well-suited for self-hosted environments and can easily run in LXC containers or Docker setups.",
"disable": false,
"install_methods": [
{
"type": "default",
"script": "ct/huntarr.sh",
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -6,7 +6,7 @@
],
"date_created": "2025-08-26",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": 8888,
"documentation": "https://docs.searxng.org/",

View File

@@ -0,0 +1,48 @@
{
"name": "SeaweedFS",
"slug": "seaweedfs",
"categories": [
11
],
"date_created": "2026-02-23",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9333,
"documentation": "https://github.com/seaweedfs/seaweedfs/wiki",
"website": "https://seaweedfs.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/seaweedfs.webp",
"config_path": "",
"description": "SeaweedFS is a fast distributed storage system for blobs, objects, files, and data lakes, with O(1) disk seek, S3 API, FUSE mount, WebDAV, and cloud tiering support.",
"install_methods": [
{
"type": "default",
"script": "ct/seaweedfs.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 16,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Master UI available at port 9333, Filer UI at port 8888, S3 API at port 8333.",
"type": "info"
},
{
"text": "Data is stored in /opt/seaweedfs-data.",
"type": "info"
},
{
"text": "FUSE mounting requires fuse3 (pre-installed).",
"type": "info"
}
]
}

View File

@@ -0,0 +1,40 @@
{
"name": "Sonobarr",
"slug": "sonobarr",
"categories": [
14
],
"date_created": "2026-02-23",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 5000,
"documentation": "https://github.com/Dodelidoo-Labs/sonobarr",
"config_path": "/etc/sonobarr/.env",
"website": "https://github.com/Dodelidoo-Labs/sonobarr",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/sonobarr.webp",
"description": "Sonobarr marries your existing Lidarr library with Last.fms discovery graph to surface artists you'll actually like. It runs as a Flask + Socket.IO application, ships with a polished Bootstrap UI, and includes admin tooling so folks can share a single instance safely.",
"install_methods": [
{
"type": "default",
"script": "ct/sonobarr.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 20,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Default generated admin password is in the env file (sonobarr_superadmin_password)",
"type": "info"
}
]
}

View File

@@ -13,11 +13,7 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"
JAVA_VERSION="21" setup_java
JAVA_VERSION="25" setup_java
NODE_VERSION="22" setup_nodejs
setup_mariadb
setup_yq
@@ -30,6 +26,11 @@ $STD npm install --force
$STD npm run build --configuration=production
msg_ok "Built Frontend"
msg_info "Embedding Frontend into Backend"
mkdir -p /opt/booklore/booklore-api/src/main/resources/static
cp -r /opt/booklore/booklore-ui/dist/booklore/browser/* /opt/booklore/booklore-api/src/main/resources/static/
msg_ok "Embedded Frontend into Backend"
msg_info "Creating Environment"
mkdir -p /opt/booklore_storage/{data,books,bookdrop}
cat <<EOF >/opt/booklore_storage/.env
@@ -41,6 +42,7 @@ DATABASE_PASSWORD=${MARIADB_DB_PASS}
# App Configuration (Spring Boot mapping from app.* properties)
APP_PATH_CONFIG=/opt/booklore_storage/data
APP_BOOKDROP_FOLDER=/opt/booklore_storage/bookdrop
SERVER_PORT=6060
EOF
msg_ok "Created Environment"
@@ -48,7 +50,7 @@ msg_info "Building Backend"
cd /opt/booklore/booklore-api
APP_VERSION=$(get_latest_github_release "booklore-app/BookLore")
yq eval ".app.version = \"${APP_VERSION}\"" -i src/main/resources/application.yaml
$STD ./gradlew clean build --no-daemon
$STD ./gradlew clean build -x test --no-daemon
mkdir -p /opt/booklore/dist
JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1)
if [[ -z "$JAR_PATH" ]]; then
@@ -58,16 +60,6 @@ fi
cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend"
msg_info "Configuring Nginx"
rm -rf /usr/share/nginx/html
ln -s /opt/booklore/booklore-ui/dist/booklore/browser /usr/share/nginx/html
rm -f /etc/nginx/sites-enabled/default
cp /opt/booklore/nginx.conf /etc/nginx/nginx.conf
sed -i 's/listen \${BOOKLORE_PORT};/listen 6060;/' /etc/nginx/nginx.conf
sed -i 's/listen \[::\]:${BOOKLORE_PORT};/listen [::]:6060;/' /etc/nginx/nginx.conf
systemctl restart nginx
msg_ok "Configured Nginx"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/booklore.service
[Unit]
@@ -78,7 +70,7 @@ After=network.target mariadb.service
Type=simple
User=root
WorkingDirectory=/opt/booklore/dist
ExecStart=/usr/bin/java -jar /opt/booklore/dist/app.jar
ExecStart=/usr/bin/java -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -jar /opt/booklore/dist/app.jar
EnvironmentFile=/opt/booklore_storage/.env
SuccessExitStatus=143
TimeoutStopSec=10

View File

@@ -13,7 +13,7 @@ setting_up_container
network_check
update_os
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
msg_info "Setup Cross-Seed"
$STD npm install cross-seed@latest -g

View File

@@ -21,6 +21,8 @@ msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
echo "${TAB3}It is important to choose the name for your server before you install Synapse, because it cannot be changed later."
echo "${TAB3}The server name determines the “domain” part of user-ids for users on your server: these will all be of the format @user:my.domain.name. It also determines how other matrix servers will reach yours for federation."
read -p "${TAB3}Please enter the name for your server: " servername
msg_info "Installing Element Synapse"

View File

@@ -13,7 +13,7 @@ setting_up_container
network_check
update_os
PHP_VERSION="8.4" PHP_APACHE="YES" setup_php
PHP_VERSION="8.5" PHP_APACHE="YES" setup_php
setup_composer
setup_mariadb
MARIADB_DB_NAME="firefly" MARIADB_DB_USER="firefly" setup_mariadb_db

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: BiluliB
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/plexguide/Huntarr.io
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y build-essential
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv
fetch_and_deploy_gh_release "huntarr" "plexguide/Huntarr.io" "tarball"
msg_info "Configure Huntarr"
$STD uv venv --clear /opt/huntarr/.venv
$STD uv pip install --python /opt/huntarr/.venv/bin/python -r /opt/huntarr/requirements.txt
msg_ok "Configured Huntrarr"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/huntarr.service
[Unit]
Description=Huntarr Service
After=network.target
[Service]
WorkingDirectory=/opt/huntarr
ExecStart=/opt/huntarr/.venv/bin/python /opt/huntarr/main.py
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now huntarr
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -26,7 +26,7 @@ msg_ok "Installed Dependencies"
setup_imagemagick
PG_VERSION="16" setup_postgresql
PG_DB_NAME="manyfold" PG_DB_USER="manyfold" setup_postgresql_db
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold/app"

View File

@@ -15,7 +15,7 @@ update_os
msg_info "Install Matterbridge"
mkdir -p /root/Matterbridge
NODE_VERSION="22" NODE_MODULE="matterbridge" setup_nodejs
NODE_VERSION="24" NODE_MODULE="matterbridge" setup_nodejs
msg_ok "Installed Matterbridge"
msg_info "Creating Service"

View File

@@ -14,7 +14,7 @@ setting_up_container
network_check
update_os
fetch_and_deploy_gh_release "memos" "usememos/memos" "prebuild" "v0.25.3" "/opt/memos" "memos*linux_amd64.tar.gz"
fetch_and_deploy_gh_release "memos" "usememos/memos" "prebuild" "latest" "/opt/memos" "memos*linux_amd64.tar.gz"
mkdir -p /opt/memos_data
msg_info "Creating Service"

View File

@@ -15,22 +15,19 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
ca-certificates \
build-essential \
python3 \
python3-setuptools \
graphicsmagick
msg_ok "Installed Dependencies"
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
msg_info "Installing n8n (Patience)"
$STD npm install --global patch-package
$STD npm install --global n8n
$STD npm install -g n8n
msg_ok "Installed n8n"
msg_info "Creating Service"
mkdir -p /opt
cat <<EOF >/opt/n8n.env
N8N_SECURE_COOKIE=false
N8N_PORT=5678

View File

@@ -14,7 +14,7 @@ network_check
update_os
fetch_and_deploy_gh_release "nodecast-tv" "technomancer702/nodecast-tv"
setup_nodejs
NODE_VERSION="20" setup_nodejs
msg_info "Installing Dependencies"
$STD apt install -y ffmpeg

View File

@@ -19,7 +19,7 @@ $STD apt install -y \
iptables
msg_ok "Installed Dependencies"
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball"
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64"
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_amd64.tar.gz"

View File

@@ -42,7 +42,7 @@ $STD apt install -y \
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.13" setup_uv
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
setup_mariadb
MARIADB_DB_NAME="romm" MARIADB_DB_USER="romm" setup_mariadb_db

View File

@@ -0,0 +1,50 @@
#!/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/seaweedfs/seaweedfs
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 fuse3
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "seaweedfs" "seaweedfs/seaweedfs" "prebuild" "latest" "/opt/seaweedfs" "linux_amd64.tar.gz"
msg_info "Setting up SeaweedFS"
mkdir -p /opt/seaweedfs-data
ln -sf /opt/seaweedfs/weed /usr/local/bin/weed
msg_ok "Set up SeaweedFS"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/seaweedfs.service
[Unit]
Description=SeaweedFS Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/seaweedfs
ExecStart=/opt/seaweedfs/weed server -dir=/opt/seaweedfs-data -master.port=9333 -volume.port=8080 -filer -s3
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now seaweedfs
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -13,7 +13,7 @@ setting_up_container
network_check
update_os
NODE_VERSION="22" setup_nodejs
NODE_VERSION="24" setup_nodejs
PG_VERSION="17" setup_postgresql
PG_DB_USER="snowshare" PG_DB_NAME="snowshare" setup_postgresql_db
fetch_and_deploy_gh_release "snowshare" "TuroYT/snowshare" "tarball"

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: GoldenSpringness
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Dodelidoo-Labs/sonobarr
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
fetch_and_deploy_gh_release "sonobarr" "Dodelidoo-Labs/sonobarr" "tarball"
PYTHON_VERSION="3.12" setup_uv
msg_info "Setting up sonobarr"
$STD uv venv -c /opt/sonobarr/venv
source /opt/sonobarr/venv/bin/activate
$STD uv pip install --no-cache-dir -r /opt/sonobarr/requirements.txt
mkdir -p /etc/sonobarr
mv /opt/sonobarr/.sample-env /etc/sonobarr/.env
sed -i "s/^secret_key=.*/secret_key=$(openssl rand -hex 16)/" /etc/sonobarr/.env
sed -i "s/^sonobarr_superadmin_password=.*/sonobarr_superadmin_password=$(openssl rand -hex 16)/" /etc/sonobarr/.env
echo "release_version=$(cat ~/.sonobarr)" >>/etc/sonobarr/.env
echo "sonobarr_config_dir=/etc/sonobarr" >>/etc/sonobarr.env
msg_ok "Set up sonobarr"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/sonobarr.service
[Unit]
Description=sonobarr Service
After=network.target
[Service]
WorkingDirectory=/opt/sonobarr/src
EnvironmentFile=/etc/sonobarr/.env
Environment="PATH=/opt/sonobarr/venv/bin"
ExecStart=/bin/bash -c 'gunicorn Sonobarr:app -c ../gunicorn_config.py'
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now sonobarr
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
$STD apt install -y build-essential
msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
NODE_VERSION="24" NODE_MODULE="verdaccio" setup_nodejs
msg_info "Configuring Verdaccio"
mkdir -p /opt/verdaccio/config

View File

@@ -23,7 +23,7 @@ $STD apt install -y \
msg_ok "Installed Dependencies"
setup_rust
NODE_MODULE="pnpm" setup_nodejs
NODE_VERSION="20" NODE_MODULE="pnpm" setup_nodejs
fetch_and_deploy_gh_release "wealthfolio" "afadil/wealthfolio" "tarball"
msg_info "Building Frontend (patience)"

View File

@@ -25,7 +25,9 @@ get_lxc_ip
# post_progress_to_api()
#
# - Lightweight progress ping from inside the container
# - Updates the existing telemetry record status from "installing" to "configuring"
# - Updates the existing telemetry record status
# - Arguments:
# * $1: status (optional, default: "configuring")
# - Signals that the installation is actively progressing (not stuck)
# - Fire-and-forget: never blocks or fails the script
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
@@ -35,9 +37,11 @@ post_progress_to_api() {
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
[[ -z "${RANDOM_UUID:-}" ]] && return 0
local progress_status="${1:-configuring}"
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
-H "Content-Type: application/json" \
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"${progress_status}\"}" &>/dev/null || true
}
# This function enables IPv6 if it's not disabled and sets verbose mode

View File

@@ -35,7 +35,11 @@
TELEMETRY_URL="https://telemetry.community-scripts.org/telemetry"
# Timeout for telemetry requests (seconds)
# Progress pings (validation/configuring) use the short timeout
TELEMETRY_TIMEOUT=5
# Final status updates (success/failed) use the longer timeout
# PocketBase may need more time under load (FindRecord + UpdateRecord)
STATUS_TIMEOUT=10
# ==============================================================================
# SECTION 0: REPOSITORY SOURCE DETECTION
@@ -741,7 +745,10 @@ EOF
# post_progress_to_api()
#
# - Lightweight progress ping from host or container
# - Updates the existing telemetry record status to "configuring"
# - Updates the existing telemetry record status
# - Arguments:
# * $1: status (optional, default: "configuring")
# Valid values: "validation", "configuring"
# - Signals that the installation is actively progressing (not stuck)
# - Fire-and-forget: never blocks or fails the script
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
@@ -752,12 +759,13 @@ post_progress_to_api() {
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
[[ -z "${RANDOM_UUID:-}" ]] && return 0
local progress_status="${1:-configuring}"
local app_name="${NSAPP:-${app:-unknown}}"
local telemetry_type="${TELEMETRY_TYPE:-lxc}"
curl -fsS -m 5 -X POST "${TELEMETRY_URL:-https://telemetry.community-scripts.org/telemetry}" \
-H "Content-Type: application/json" \
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${telemetry_type}\",\"nsapp\":\"${app_name}\",\"status\":\"configuring\"}" &>/dev/null || true
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${telemetry_type}\",\"nsapp\":\"${app_name}\",\"status\":\"${progress_status}\"}" &>/dev/null || true
}
# ------------------------------------------------------------------------------
@@ -893,7 +901,7 @@ post_update_to_api() {
EOF
)
http_code=$(curl -sS -w "%{http_code}" -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
http_code=$(curl -sS -w "%{http_code}" -m "${STATUS_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" -o /dev/null 2>/dev/null) || http_code="000"
@@ -936,7 +944,7 @@ EOF
EOF
)
http_code=$(curl -sS -w "%{http_code}" -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
http_code=$(curl -sS -w "%{http_code}" -m "${STATUS_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \
-d "$RETRY_PAYLOAD" -o /dev/null 2>/dev/null) || http_code="000"
@@ -964,12 +972,18 @@ EOF
EOF
)
curl -sS -w "%{http_code}" -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
http_code=$(curl -sS -w "%{http_code}" -m "${STATUS_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \
-d "$MINIMAL_PAYLOAD" -o /dev/null 2>/dev/null || true
-d "$MINIMAL_PAYLOAD" -o /dev/null 2>/dev/null) || http_code="000"
# Tried 3 times - mark as done regardless to prevent infinite loops
POST_UPDATE_DONE=true
if [[ "$http_code" =~ ^2[0-9]{2}$ ]]; then
POST_UPDATE_DONE=true
return 0
fi
# All 3 attempts failed — do NOT set POST_UPDATE_DONE=true.
# This allows the EXIT trap (api_exit_script) to retry with 3 fresh attempts.
# No infinite loop risk: EXIT trap fires exactly once.
}
# ==============================================================================
@@ -1345,9 +1359,27 @@ post_update_to_api_extended() {
EOF
)
curl -fsS -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
local http_code
http_code=$(curl -sS -w "%{http_code}" -m "${STATUS_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD" &>/dev/null || true
-d "$JSON_PAYLOAD" -o /dev/null 2>/dev/null) || http_code="000"
POST_UPDATE_DONE=true
if [[ "$http_code" =~ ^2[0-9]{2}$ ]]; then
POST_UPDATE_DONE=true
return 0
fi
# Retry with minimal payload
sleep 1
http_code=$(curl -sS -w "%{http_code}" -m "${STATUS_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
-H "Content-Type: application/json" \
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${TELEMETRY_TYPE:-lxc}\",\"nsapp\":\"${NSAPP:-unknown}\",\"status\":\"${pb_status}\",\"exit_code\":${exit_code},\"install_duration\":${duration:-0}}" \
-o /dev/null 2>/dev/null) || http_code="000"
if [[ "$http_code" =~ ^2[0-9]{2}$ ]]; then
POST_UPDATE_DONE=true
return 0
fi
# Do NOT set POST_UPDATE_DONE=true — let EXIT trap retry
}

View File

@@ -3671,6 +3671,9 @@ $PCT_OPTIONS_STRING"
create_lxc_container || exit $?
# Transition to 'configuring' — container created, now setting up OS/userland
post_progress_to_api "configuring"
LXC_CONFIG="/etc/pve/lxc/${CTID}.conf"
# ============================================================================
@@ -3912,7 +3915,6 @@ EOF
for i in {1..10}; do
if pct status "$CTID" | grep -q "status: running"; then
msg_ok "Started LXC Container"
post_progress_to_api # Signal container is running
break
fi
sleep 1
@@ -3967,7 +3969,6 @@ EOF
echo -e "${YW}Container may have limited internet access. Installation will continue...${CL}"
else
msg_ok "Network in LXC is reachable (ping)"
post_progress_to_api # Signal network is ready
fi
fi
# Function to get correct GID inside container
@@ -4039,7 +4040,6 @@ EOF'
fi
msg_ok "Customized LXC Container"
post_progress_to_api # Signal ready for app installation
# Optional DNS override for retry scenarios (inside LXC, never on host)
if [[ "${DNS_RETRY_OVERRIDE:-false}" == "true" ]]; then
@@ -4064,8 +4064,15 @@ EOF'
# that sends "configuring" status AFTER the host already reported "failed"
export CONTAINER_INSTALLING=true
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local lxc_exit=$?
# Capture lxc-attach terminal output to host-side log via tee.
# This is the ONLY reliable way to get install output when:
# - install.func fails to load (DNS error) → no container-side logging
# - install script crashes before logging starts
# - $STD/silent() not used for some commands
# PIPESTATUS[0] gets the real exit code from lxc-attach (not from tee).
local _LXC_CAPTURE_LOG="/tmp/.install-capture-${SESSION_ID}.log"
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)" 2>&1 | tee "$_LXC_CAPTURE_LOG"
local lxc_exit=${PIPESTATUS[0]}
unset CONTAINER_INSTALLING
@@ -4123,7 +4130,17 @@ EOF'
# Copy and append INSTALL_LOG from container (with timeout to prevent hangs)
local temp_install_log="/tmp/.install-temp-${SESSION_ID}.log"
local container_log_ok=false
if timeout 8 pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_install_log" 2>/dev/null; then
# Only use container log if it has meaningful content (>100 bytes)
if [[ -s "$temp_install_log" ]] && [[ $(stat -c%s "$temp_install_log" 2>/dev/null || echo 0) -gt 100 ]]; then
container_log_ok=true
fi
fi
# PHASE 2: Use container-side log if available, otherwise use host-captured tee output
local _LXC_CAPTURE_LOG="/tmp/.install-capture-${SESSION_ID}.log"
if [[ "$container_log_ok" == true ]]; then
{
echo "================================================================================"
echo "PHASE 2: APPLICATION INSTALLATION (Container)"
@@ -4131,9 +4148,25 @@ EOF'
cat "$temp_install_log"
echo ""
} >>"$combined_log"
rm -f "$temp_install_log"
install_log_copied=true
# Point INSTALL_LOG to combined log so get_error_text() finds it
elif [[ -s "$_LXC_CAPTURE_LOG" ]]; then
# Fallback: host-captured terminal output from lxc-attach
# This captures everything the user saw, including errors when install.func
# failed to load (DNS issues, etc.) and no container-side logging was set up.
{
echo "================================================================================"
echo "PHASE 2: APPLICATION INSTALLATION (Container - captured from terminal)"
echo "================================================================================"
# Strip ANSI escape codes from terminal capture
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' "$_LXC_CAPTURE_LOG" | sed 's/\r$//'
echo ""
} >>"$combined_log"
install_log_copied=true
fi
rm -f "$temp_install_log"
if [[ "$install_log_copied" == true ]]; then
# Point INSTALL_LOG to combined log so get_full_log() finds it
INSTALL_LOG="$combined_log"
fi
fi
@@ -4393,8 +4426,9 @@ EOF'
# Re-run install script in existing container (don't destroy/recreate)
set +Eeuo pipefail
trap - ERR
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local apt_retry_exit=$?
local _LXC_CAPTURE_LOG="/tmp/.install-capture-${SESSION_ID}.log"
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)" 2>&1 | tee "$_LXC_CAPTURE_LOG"
local apt_retry_exit=${PIPESTATUS[0]}
set -Eeuo pipefail
trap 'error_handler' ERR
@@ -4500,6 +4534,9 @@ EOF'
exit $install_exit_code
fi
# Clean up host-side capture log (not needed on success, already in combined_log on failure)
rm -f "/tmp/.install-capture-${SESSION_ID}.log" 2>/dev/null
# Re-enable error handling after successful install or recovery menu completion
set -Eeuo pipefail
trap 'error_handler' ERR
@@ -4910,6 +4947,9 @@ create_lxc_container() {
# Report installation start to API early - captures failures in storage/template/create
post_to_api
# Transition to 'validation' — Proxmox-internal checks (storage, template, cluster)
post_progress_to_api "validation"
# Storage capability check
check_storage_support "rootdir" || {
msg_error "No valid storage found for 'rootdir' [Container]"
@@ -5439,7 +5479,6 @@ create_lxc_container() {
}
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
post_progress_to_api # Signal container creation complete
}
# ==============================================================================

View File

@@ -488,7 +488,7 @@ log_section() {
# silent()
#
# - Executes command with output redirected to active log file
# - On error: displays last 10 lines of log and exits with original exit code
# - On error: displays last 20 lines of log and exits with original exit code
# - Temporarily disables error trap to capture exit code correctly
# - Sources explain_exit_code() for detailed error messages
# ------------------------------------------------------------------------------
@@ -530,8 +530,8 @@ silent() {
msg_custom "→" "${YWB}" "${cmd}"
if [[ -s "$logfile" ]]; then
echo -e "\n${TAB}--- Last 10 lines of log ---"
tail -n 10 "$logfile"
echo -e "\n${TAB}--- Last 20 lines of log ---"
tail -n 20 "$logfile"
echo -e "${TAB}-----------------------------------"
echo -e "${TAB}📋 Full log: ${logfile}\n"
fi
@@ -1505,7 +1505,7 @@ cleanup_lxc() {
fi
msg_ok "Cleaned"
# Send progress ping if available (defined in install.func)
if declare -f post_progress_to_api &>/dev/null; then
post_progress_to_api

View File

@@ -51,7 +51,9 @@ get_lxc_ip
# post_progress_to_api()
#
# - Lightweight progress ping from inside the container
# - Updates the existing telemetry record status from "installing" to "configuring"
# - Updates the existing telemetry record status
# - Arguments:
# * $1: status (optional, default: "configuring")
# - Signals that the installation is actively progressing (not stuck)
# - Fire-and-forget: never blocks or fails the script
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
@@ -61,9 +63,11 @@ post_progress_to_api() {
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
[[ -z "${RANDOM_UUID:-}" ]] && return 0
local progress_status="${1:-configuring}"
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
-H "Content-Type: application/json" \
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
-d "{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"${progress_status}\"}" &>/dev/null || true
}
# ==============================================================================

View File

@@ -1525,6 +1525,82 @@ verify_gpg_fingerprint() {
return 1
}
# ------------------------------------------------------------------------------
# Get latest GitHub tag for a repository.
#
# Description:
# - Queries the GitHub API for tags (not releases)
# - Useful for repos that only create tags, not full releases
# - Supports optional prefix filter and version-only extraction
# - Returns the latest tag name (printed to stdout)
#
# Usage:
# MONGO_VERSION=$(get_latest_gh_tag "mongodb/mongo-tools")
# LATEST=$(get_latest_gh_tag "owner/repo" "v") # only tags starting with "v"
# LATEST=$(get_latest_gh_tag "owner/repo" "" "true") # strip leading "v"
#
# Arguments:
# $1 - GitHub repo (owner/repo)
# $2 - Tag prefix filter (optional, e.g. "v" or "100.")
# $3 - Strip prefix from result (optional, "true" to strip $2 prefix)
#
# Returns:
# 0 on success (tag printed to stdout), 1 on failure
#
# Notes:
# - Skips tags containing "rc", "alpha", "beta", "dev", "test"
# - Sorts by version number (sort -V) to find the latest
# - Respects GITHUB_TOKEN for rate limiting
# ------------------------------------------------------------------------------
get_latest_gh_tag() {
local repo="$1"
local prefix="${2:-}"
local strip_prefix="${3:-false}"
local header_args=()
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
local http_code=""
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_tags.json \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"${header_args[@]}" \
"https://api.github.com/repos/${repo}/tags?per_page=100" 2>/dev/null) || true
if [[ "$http_code" == "403" ]]; then
msg_warn "GitHub API rate limit exceeded while fetching tags for ${repo}"
rm -f /tmp/gh_tags.json
return 1
fi
if [[ "$http_code" != "200" ]] || [[ ! -s /tmp/gh_tags.json ]]; then
rm -f /tmp/gh_tags.json
return 1
fi
local tags_json
tags_json=$(</tmp/gh_tags.json)
rm -f /tmp/gh_tags.json
# Extract tag names, filter by prefix, exclude pre-release patterns, sort by version
local latest=""
latest=$(echo "$tags_json" | grep -oP '"name":\s*"\K[^"]+' |
{ [[ -n "$prefix" ]] && grep "^${prefix}" || cat; } |
grep -viE '(rc|alpha|beta|dev|test|preview|snapshot)' |
sort -V | tail -n1)
if [[ -z "$latest" ]]; then
return 1
fi
if [[ "$strip_prefix" == "true" && -n "$prefix" ]]; then
latest="${latest#"$prefix"}"
fi
echo "$latest"
return 0
}
# ==============================================================================
# INSTALL FUNCTIONS
# ==============================================================================

View File

@@ -169,7 +169,7 @@ get_active_logfile() {
# silent()
#
# - Executes command with output redirected to active log file
# - On error: displays last 10 lines of log and exits with original exit code
# - On error: displays last 20 lines of log and exits with original exit code
# - Temporarily disables error trap to capture exit code correctly
# - Sources explain_exit_code() for detailed error messages
# ------------------------------------------------------------------------------
@@ -207,8 +207,8 @@ silent() {
msg_custom "→" "${YWB}" "${cmd}"
if [[ -s "$logfile" ]]; then
echo -e "\n${TAB}--- Last 10 lines of log ---"
tail -n 10 "$logfile"
echo -e "\n${TAB}--- Last 20 lines of log ---"
tail -n 20 "$logfile"
echo -e "${TAB}----------------------------\n"
fi

219
tools/addon/arcane.sh Normal file
View File

@@ -0,0 +1,219 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: summoningpixels
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/getarcaneapp/arcane
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Arcane"
APP_TYPE="addon"
INSTALL_PATH="/opt/arcane"
COMPOSE_FILE="${INSTALL_PATH}/compose.yaml"
ENV_FILE="${INSTALL_PATH}/.env"
DEFAULT_PORT=3552
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
___ ____ _________ _ ________
/ | / __ \/ ____/ | / | / / ____/
/ /| | / /_/ / / / /| | / |/ / __/
/ ___ |/ _, _/ /___/ ___ |/ /| / /___
/_/ |_/_/ |_|\____/_/ |_/_/ |_/_____/
EOF
}
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
if [[ -f "$COMPOSE_FILE" ]]; then
msg_info "Stopping and removing Docker containers"
cd "$INSTALL_PATH"
$STD docker compose down --volumes --remove-orphans
msg_ok "Stopped and removed Docker containers"
fi
rm -rf "$INSTALL_PATH"
rm -f "/usr/local/bin/update_arcane"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
msg_info "Pulling latest ${APP} image"
cd "$INSTALL_PATH"
$STD docker compose pull
msg_ok "Pulled latest image"
msg_info "Restarting ${APP}"
$STD docker compose up -d --remove-orphans
msg_ok "Restarted ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# CHECK DOCKER
# ==============================================================================
function check_docker() {
if ! command -v docker &>/dev/null; then
msg_error "Docker is not installed. This script requires an existing Docker LXC. Exiting."
exit 1
fi
if ! docker compose version &>/dev/null; then
msg_error "Docker Compose plugin is not available. Please install it before running this script. Exiting."
exit 1
fi
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_docker
msg_info "Creating install directory"
mkdir -p "$INSTALL_PATH"
msg_ok "Created ${INSTALL_PATH}"
# Generate secrets and config values
local ENCRYPTION_KEY JWT_SECRET PROJ_DIR
ENCRYPTION_KEY=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
JWT_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
PROJ_DIR="/etc/arcane/projects"
msg_info "Creating stacks directory"
mkdir -p "$PROJ_DIR"
msg_ok "Created ${PROJ_DIR}"
msg_info "Downloading Docker Compose file"
curl -fsSL "https://raw.githubusercontent.com/getarcaneapp/arcane/refs/heads/main/docker/examples/compose.basic.yaml" -o "$COMPOSE_FILE"
msg_ok "Downloaded Docker Compose file"
msg_info "Downloading .env file"
curl -fsSL "https://raw.githubusercontent.com/getarcaneapp/arcane/refs/heads/main/.env.example" -o "$ENV_FILE"
chmod 600 "$ENV_FILE"
msg_ok "Downloaded .env file"
msg_info "Configuring compose and env files"
sed -i '/^[[:space:]]*#/!s|/host/path/to/projects|'"$PROJ_DIR"'|g' "$COMPOSE_FILE"
sed -i '/^[[:space:]]*#/!s|ENCRYPTION_KEY=.*|ENCRYPTION_KEY='"$ENCRYPTION_KEY"'|g' "$COMPOSE_FILE"
sed -i '/^[[:space:]]*#/!s|JWT_SECRET=.*|JWT_SECRET='"$JWT_SECRET"'|g' "$COMPOSE_FILE"
sed -i '/^[[:space:]]*#/!s|APP_URL=.*|APP_URL=http://localhost:'"$DEFAULT_PORT"'|g' "$ENV_FILE"
sed -i '/^[[:space:]]*#/!s|ENCRYPTION_KEY=.*|#&|g' "$ENV_FILE"
sed -i '/^[[:space:]]*#/!s|JWT_SECRET=.*|#&|g' "$ENV_FILE"
msg_ok "Configured compose and env files"
msg_info "Starting ${APP}"
cd "$INSTALL_PATH"
$STD docker compose up -d
msg_ok "Started ${APP}"
# Create update script
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_arcane
#!/usr/bin/env bash
# Arcane Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/arcane.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_arcane
msg_ok "Created update script (/usr/local/bin/update_arcane)"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
echo ""
echo -e "Arcane Credentials"
echo -e "=================="
echo -e "User: arcane"
echo -e "Password: arcane-admin"
echo ""
msg_warn "On first access, you'll be prompted to change your password."
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -f "$COMPOSE_FILE" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
fi
exit 0
fi
header_info
get_lxc_ip
# Check if already installed
if [[ -f "$COMPOSE_FILE" ]]; then
msg_warn "${APP} is already installed."
echo ""
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
fi
echo -n "${TAB}Update ${APP}? (y/N): "
read -r update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
update
exit 0
fi
msg_warn "No action selected. Exiting."
exit 0
fi
# Fresh installation
msg_warn "${APP} is not installed."
echo ""
echo -e "${TAB}${INFO} This will install:"
echo -e "${TAB} - Arcane (via Docker Compose)"
echo ""
echo -n "${TAB}Install ${APP}? (y/N): "
read -r install_prompt
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
install
else
msg_warn "Installation cancelled. Exiting."
exit 0
fi

6
tools/headers/arcane Normal file
View File

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