Compare commits

...

104 Commits

Author SHA1 Message Date
Michel Roegl-Brunner
50a8134492 huntarr-install.sh 2026-02-23 18:12:27 +01:00
Michel Roegl-Brunner
fea6521dd2 huntarr.sh 2026-02-23 18:11:49 +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
CanbiZ (MickLesk)
60f9622998 fix(core): keep host-side logging on BUILD_LOG after INSTALL_LOG export
After 'export INSTALL_LOG' in build.func, get_active_logfile() returned
the container's INSTALL_LOG path for all host-side logging, causing
msg_info/msg_ok/msg_error on the host to write to /root/.install-SESSION.log
(the host file, not the container's) instead of BUILD_LOG. This made
BUILD_LOG incomplete and get_full_log() unable to send full traces.

Fix: Add _HOST_LOGFILE (not exported, invisible to container) so the host
always logs to BUILD_LOG. Container still uses INSTALL_LOG as before.
2026-02-23 16:07:13 +01:00
community-scripts-pr-app[bot]
552f3ab1d4 Update CHANGELOG.md (#12219)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 13:53:28 +00:00
JohnFII
aa54640798 chore: update Frigate documentation and website URLs (#12218) 2026-02-23 14:52:59 +01:00
community-scripts-pr-app[bot]
e1a8dfa8a2 Update CHANGELOG.md (#12217)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 13:31:19 +00:00
CanbiZ (MickLesk)
691cec80ab core: Enhance signal handling, reported "status" and logs (#12216)
* Enhance telemetry, signal handling, and logs

Improve failure telemetry and signal handling across the installer: add get_full_log() to collect/strip/truncate install logs and include them in API payloads with a truncated retry; add CONTAINER_INSTALLING flag around lxc-attach and stop containers on abort to avoid orphaned "installing/configuring" records; introduce _send_abort_telemetry() (curl fallback for container context) and _stop_container_if_installing() helpers; centralize and simplify EXIT/ERR/INT/TERM/HUP traps and handlers (including a new on_hangup handler) and update VM scripts to report numeric exit codes. Also ensure best-effort log collection is performed and tweak error categorization for certain signals.

* Include full log in error telemetry

Use get_full_log (up to 120KB) to populate the error telemetry field so the API receives the full installation trace; fall back to get_error_text (last ~20 lines) if the full log is empty. Removed collection and inclusion of a separate install_log field from the JSON payloads and simplified the retry payloads/comments accordingly. The change ensures error reports contain the complete trace while avoiding duplicate large log fields and keeps graceful failure handling (get_full_log || true).

* Anonymize IP addresses in get_full_log

Mask IPv4 addresses in logs when collecting full log output: added a sed step that replaces the last two octets with "x.x" to avoid exposing full IPs (GDPR). Also updated the comment to reflect anonymization; existing steps that strip carriage returns and ANSI escape sequences remain in place before truncating with head -c.
2026-02-23 14:30:48 +01:00
community-scripts-pr-app[bot]
c1ec478269 Update .app files (#12213)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 13:42:31 +01:00
community-scripts-pr-app[bot]
0e8f9c1237 Update CHANGELOG.md (#12215)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:38:40 +00:00
community-scripts-pr-app[bot]
620db1901c Update CHANGELOG.md (#12214)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:38:19 +00:00
community-scripts-pr-app[bot]
d5ce186aa3 Update date in json (#12212)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:38:11 +00:00
push-app-to-main[bot]
68fbed63a5 SparkyFitness (#12185)
* Add sparkyfitness (ct)

* Fix URL and improve backup commands in script

* Fix path formatting in installation script

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-02-23 13:37:54 +01:00
community-scripts-pr-app[bot]
973970ee1a Update CHANGELOG.md (#12211)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:37:37 +00:00
Kenny Laevaert
b30e86aa2f Update default credentials (#12201)
Updated default credentials.
2026-02-23 13:37:14 +01:00
CanbiZ (MickLesk)
a13caec262 allow Frigate's Intel media packages to overwrite files from system GPU driver packages 2026-02-23 13:25:20 +01:00
community-scripts-pr-app[bot]
df80c849f2 Update CHANGELOG.md (#12209)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:22:33 +00:00
CanbiZ (MickLesk)
69de9fa57e Improve error handling and logging for LXC builds (#12208)
Prevent host-side error_handler from being triggered during in-container install/recovery by delaying re-enabling set -Eeuo pipefail and the ERR trap in misc/build.func until after install/recovery completes; add explanatory comments. Update misc/error_handler.func to fall back to BUILD_LOG if container-internal log path is unavailable, show the last 20 log lines when present, refine container vs host detection (check INSTALL_LOG file and /root), copy INSTALL_LOG into /root and write a .failed flag with the exit code for host-side detection, and ensure full-log output and container removal prompt are shown appropriately in host context. Tweak misc/core.func silent() output to include a "Full log" path and adjust formatting.
2026-02-23 13:22:09 +01:00
community-scripts-pr-app[bot]
695a6ce29b chore: update github-versions.json (#12206)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 12:14:28 +00:00
CanbiZ (MickLesk)
1976a1715c bookworm arc support 2026-02-23 13:08:39 +01:00
CanbiZ (MickLesk)
6ba22c82d7 Add Signed-By to Debian APT source entries
Update misc/tools.func to include Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg on multiple Debian repository blocks (bullseye, bookworm, trixie/sid and their -security entries) for non-free and non-free-firmware components. This ensures APT uses the specified keyring to verify repository metadata and improves reproducible/secure apt configuration.
2026-02-23 12:59:42 +01:00
community-scripts-pr-app[bot]
1a14b19fa0 Update CHANGELOG.md (#12204)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 11:14:58 +00:00
community-scripts-pr-app[bot]
9e6b1f0e12 Update CHANGELOG.md (#12203)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 11:14:44 +00:00
community-scripts-pr-app[bot]
103982fcdb Update date in json (#12202)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-23 11:14:35 +00:00
CanbiZ (MickLesk)
e315e0b17e Frigate v16.4 (#11887)
* Update frigate.sh

* Add Frigate metadata and overhaul installer

Add frontend metadata for Frigate (frontend/public/json/frigate.json), remove the old .bak metadata file, and perform a major refactor of install/frigate-install.sh. The installer now targets Debian 12 (Bookworm), converts APT sources to deb822, installs and builds required dependencies (Python wheels, libusb, OpenVINO, Tempio, Nginx, sqlite extensions), configures hardware acceleration and GPU access, fetches and deploys Frigate and go2rtc releases, and prepares inference/audio models. Systemd service units were improved (dependencies, env file usage, safer log file handling, create_directories service) and services are enabled/started with cleanup steps added. Also updated copyright/authorship and various runtime environment exports and default Frigate config changes (ffmpeg hwaccel, detector selection, disabled auth/detect in default config).

* Update frigate.json

* frigate: update metadata and installer

Update frontend metadata (config path, interface port, and expanded description) and modernize the install script: switch apt-get to apt, streamline dependency list (remove wget/jq/unzip), replace inline hardware-acceleration/GPU group tweaks with setup_hwaccel, pin Frigate release to v0.16.4 for reproducible installs, and fetch/libusb build now uses fetch_and_deploy_gh_release with adjusted paths. Also clean up removed temporary files.

* add std
2026-02-23 12:14:17 +01:00
community-scripts-pr-app[bot]
2a537f0772 chore: update github-versions.json (#12199)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 06:26:21 +00:00
community-scripts-pr-app[bot]
9d7da517f3 Update CHANGELOG.md (#12198)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 00:22:42 +00:00
community-scripts-pr-app[bot]
c1248cca14 chore: update github-versions.json (#12197)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 00:22:19 +00:00
community-scripts-pr-app[bot]
a83cd9a80e Update CHANGELOG.md (#12196)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 20:44:06 +00:00
community-scripts-pr-app[bot]
203c1f2f48 Update CHANGELOG.md (#12195)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 20:43:54 +00:00
CanbiZ (MickLesk)
287fe28741 Refactor & Bump to v2: Plex (#12179) 2026-02-22 21:43:40 +01:00
community-scripts-pr-app[bot]
d868b6d885 Update CHANGELOG.md (#12194)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 20:43:31 +00:00
community-scripts-pr-app[bot]
3995aa02da Update CHANGELOG.md (#12193)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 20:43:16 +00:00
Copilot
2b44ff289f fix: Apache Guacamole - bump to Temurin JDK 17 to resolve Debian 13 (Trixie) install failure (#12161) 2026-02-22 21:43:05 +01:00
community-scripts-pr-app[bot]
47757d4d7d Update CHANGELOG.md (#12192)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 20:42:55 +00:00
CanbiZ (MickLesk)
ee90bfb458 Docker-VM: add error handling for virt-customize finalization (#12127) 2026-02-22 21:42:34 +01:00
MickLesk
3e22aaa4bb qf libgirepository1.0 2026-02-22 19:30:50 +01:00
community-scripts-pr-app[bot]
618133ffca chore: update github-versions.json (#12191)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 18:08:42 +00:00
community-scripts-pr-app[bot]
ded8a95567 Update CHANGELOG.md (#12190)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 17:56:07 +00:00
Chris
85502e7c43 [Fix] Sure: add Sidekiq service (#12186) 2026-02-22 18:55:41 +01:00
community-scripts-pr-app[bot]
a8bec558f9 Update .app files (#12188)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-22 17:14:03 +01:00
community-scripts-pr-app[bot]
5c7934a71e Update CHANGELOG.md (#12187)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 16:08:17 +00:00
Tobias
adf6a03067 karakeep: bump to node 24 (#12183) 2026-02-22 11:07:52 -05:00
community-scripts-pr-app[bot]
f4cf671694 chore: update github-versions.json (#12182)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 12:08:50 +00:00
community-scripts-pr-app[bot]
2f364d2fca Update CHANGELOG.md (#12181)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:54:52 +00:00
community-scripts-pr-app[bot]
88008b8735 Update CHANGELOG.md (#12180)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:54:41 +00:00
CanbiZ (MickLesk)
07eae3a06f calibre-web: Update logo URL (#12178) 2026-02-22 11:54:28 +01:00
CanbiZ (MickLesk)
171d830c22 fix(tools): add GitHub API rate-limit detection and GITHUB_TOKEN support (#12176)
- check_for_gh_release: add Authorization header when GITHUB_TOKEN is set,
  detect HTTP 403 and show actionable rate-limit hint
- fetch_and_deploy_gh_release: improve retry loop with specific 403 handling,
  exponential backoff, and token export hint on rate-limit failure
2026-02-22 11:54:21 +01:00
MickLesk
4e8421c080 Merge branch 'main' of https://github.com/community-scripts/ProxmoxVE 2026-02-22 11:40:10 +01:00
MickLesk
0c92f40d7a name of cronmaster 2026-02-22 11:40:06 +01:00
community-scripts-pr-app[bot]
104971ada3 Update CHANGELOG.md (#12177)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:38:30 +00:00
Joerg Heinemann
9db0ff6d81 Update package management commands in clean-lxcs.sh (#12166)
Replace 'apt-get' with 'apt' for package management commands.
2026-02-22 11:38:10 +01:00
MickLesk
b05f0fb059 switch type of cronmaster to addon 2026-02-22 11:37:23 +01:00
community-scripts-pr-app[bot]
345e7f741b Update .app files (#12171)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-22 11:34:28 +01:00
community-scripts-pr-app[bot]
452f3bdc6a Update CHANGELOG.md (#12175)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:32:55 +00:00
community-scripts-pr-app[bot]
d287b5f848 Update CHANGELOG.md (#12174)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:32:39 +00:00
community-scripts-pr-app[bot]
80a435fc9f Update date in json (#12173)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:32:34 +00:00
push-app-to-main[bot]
2e32ea3c52 CR*NMASTER (#12065)
* Add cronmaster (addon)

* minor fixes

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: MickLesk <mickey.leskowitz@gmail.com>
2026-02-22 11:32:18 +01:00
community-scripts-pr-app[bot]
0753521739 Update CHANGELOG.md (#12172)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:27:16 +00:00
community-scripts-pr-app[bot]
e93949a3d2 Update CHANGELOG.md (#12170)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:26:56 +00:00
community-scripts-pr-app[bot]
c7dcedc23c Update date in json (#12169)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-22 10:26:52 +00:00
push-app-to-main[bot]
2407a633e7 Gramps-Web (#12157)
* Add gramps-web (ct)

* -

* minor fixes in install

* minor fixes

* remove empty line

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: MickLesk <mickey.leskowitz@gmail.com>
2026-02-22 11:26:36 +01:00
community-scripts-pr-app[bot]
c0b8d25b66 chore: update github-versions.json (#12165)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 06:17:08 +00:00
community-scripts-pr-app[bot]
b0112f83e9 chore: update github-versions.json (#12164)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 00:21:41 +00:00
community-scripts-pr-app[bot]
f0ed8db337 Update CHANGELOG.md (#12163)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 00:05:00 +00:00
community-scripts-pr-app[bot]
0eaaac7dea Archive old changelog entries (#12162)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-22 00:04:39 +00:00
community-scripts-pr-app[bot]
802cbdd22b chore: update github-versions.json (#12156)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 18:07:24 +00:00
community-scripts-pr-app[bot]
4f9490184b Update CHANGELOG.md (#12155)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 18:03:45 +00:00
Slaviša Arežina
b5288692cd Update documentation URL in mediamanager.json (#12154) 2026-02-21 19:03:22 +01:00
community-scripts-pr-app[bot]
8cc2c7c025 Update CHANGELOG.md (#12150)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 13:48:47 +00:00
CanbiZ (MickLesk)
85c5d54a12 fix(pangolin): restore config before db migration, use drizzle-kit push (#12130)
npm run db:push ran drizzle migrate (CREATE TABLE) on an empty directory
before the config backup was restored, creating a fresh DB that got
immediately overwritten by the old backup. The old DB was missing new
columns like resources.postAuthPath (added in 1.15.4).

Replace with drizzle-kit push after config restore, which introspects the
existing DB and applies schema diffs (ALTER TABLE) instead.

Ref: #12068
2026-02-21 14:48:22 +01:00
community-scripts-pr-app[bot]
1273778dc2 Update CHANGELOG.md (#12149)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 12:09:00 +00:00
community-scripts-pr-app[bot]
2a7fa5addb chore: update github-versions.json (#12148)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 12:08:33 +00:00
community-scripts-pr-app[bot]
116888201c Update CHANGELOG.md (#12145)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 08:10:48 +00:00
Daniel Bates
a3d9ea7530 Fix #12066: PLANKA: fix msg_info/msg_ok inconsistencies in update script (#12143)
Co-authored-by: Your Name <your-email@example.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 09:10:22 +01:00
community-scripts-pr-app[bot]
903e63d758 chore: update github-versions.json (#12144)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 06:13:39 +00:00
community-scripts-pr-app[bot]
901b90f956 Update CHANGELOG.md (#12139)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 00:21:15 +00:00
community-scripts-pr-app[bot]
8795cfb03f chore: update github-versions.json (#12138)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-21 00:20:50 +00:00
community-scripts-pr-app[bot]
ae834cb39e Update CHANGELOG.md (#12136)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 21:58:16 +00:00
CanbiZ (MickLesk)
7dbd1fdc36 recyclarr: adjust paths for v8.0 breaking changes (#12129)
Recyclarr v8.0 moved local includes from configs/ to a dedicated
includes/ directory. The install script now creates both dirs
upfront. The update script migrates existing include subdirs
from configs/ to includes/ after the binary update and also
handles detection for both old (recyclarr.yml) and new
(configs/) config layouts.

See https://recyclarr.dev/guide/upgrade-guide/v8.0

Ref #12109
2026-02-20 22:57:56 +01:00
community-scripts-pr-app[bot]
300f8c80e8 Update CHANGELOG.md (#12135)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 21:53:38 +00:00
CanbiZ (MickLesk)
d969969c2d planka: migrate data paths to new v2 directory structure (#12128)
Planka v2.0.1 moved all uploads to a unified data directory:
- public/{favicons,user-avatars,background-images} -> data/protected/
- private/attachments -> data/private/

The update script was still restoring files to the old locations,
which made attachments, avatars and backgrounds disappear after
updating from rc.4 to 2.0.1.

Changes:
- update_script: backup handles both old and new layouts
- update_script: restore now uses new v2 paths
- install script: create v2 data directories on fresh install

Ref #12066
2026-02-20 22:53:15 +01:00
community-scripts-pr-app[bot]
f6558953bc Update CHANGELOG.md (#12133)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 21:52:50 +00:00
CanbiZ (MickLesk)
b9f4e6c8bd fix(zammad): fix Elasticsearch JVM config and add daemon-reload (#12125)
The JVM heap options were appended with >> which left the old
defaults in place. Use sed to replace them instead.
Also add the missing systemctl daemon-reload that ES requires
after package installation before the service can be started.

Closes #12111
2026-02-20 22:52:28 +01:00
community-scripts-pr-app[bot]
54031b56d6 Update CHANGELOG.md (#12132)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 21:51:48 +00:00
CanbiZ (MickLesk)
c68b9b6a40 Huntarr: add build-essential for native pip dependencies (#12126)
* fix(huntarr): add build-essential for native pip dependencies

Some Python packages in requirements.txt need a C++ compiler for
native extensions. Without build-essential the uv pip install
step fails with 'command c++ not found'.

Closes #12117

* Change apt-get to apt for installing dependencies

* Ensure git dependency before updating Huntarr

Added dependency check for git before fetching and deploying the GitHub release.

* drunk
2026-02-20 22:51:26 +01:00
community-scripts-pr-app[bot]
f4c10ed75d Update CHANGELOG.md (#12131)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:56:12 +00:00
Chris
097ee57598 [Hotfix] Dokploy: fix update (#12116) 2026-02-20 21:55:51 +01:00
community-scripts-pr-app[bot]
120aefbdfe Update .app files (#12120)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-20 21:06:41 +01:00
community-scripts-pr-app[bot]
fc612ad369 Update CHANGELOG.md (#12123)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:06:08 +00:00
community-scripts-pr-app[bot]
c061434dd7 Update date in json (#12122)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:06:01 +00:00
community-scripts-pr-app[bot]
7b01ed0a90 Update CHANGELOG.md (#12121)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:05:58 +00:00
push-app-to-main[bot]
de94a3b0c8 Sure (#12114)
* Add sure (ct)

* Update service messages in sure.sh script

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Chris <punk.sand7393@fastmail.com>
2026-02-20 21:05:42 +01:00
community-scripts-pr-app[bot]
f25a150fa1 Update CHANGELOG.md (#12119)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:05:33 +00:00
community-scripts-pr-app[bot]
fd44c98235 Update date in json (#12118)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-02-20 20:05:30 +00:00
push-app-to-main[bot]
c754d0c369 Calibre-Web (#12115)
* Add calibre-web (ct)

* Fix casing in Calibre-Web references

* Correct case for Calibre-Web in installation script

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Chris <punk.sand7393@fastmail.com>
2026-02-20 21:05:09 +01:00
community-scripts-pr-app[bot]
bc5af1a536 chore: update github-versions.json (#12113)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 18:14:34 +00:00
community-scripts-pr-app[bot]
53f89258a4 chore: update github-versions.json (#12108)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 12:12:26 +00:00
community-scripts-pr-app[bot]
97302789d9 Update CHANGELOG.md (#12105)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 08:12:52 +00:00
Rik
f3b38e2ba2 fixen broken link to dawarich documentation (#12103) 2026-02-20 09:12:21 +01:00
community-scripts-pr-app[bot]
eff0963023 chore: update github-versions.json (#12102)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-20 06:20:06 +00:00
68 changed files with 2590 additions and 878 deletions

179
.github/changelogs/2026/02.md generated vendored
View File

@@ -1,3 +1,182 @@
## 2026-02-21
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Pangolin: restore config before db migration, use drizzle-kit push [@MickLesk](https://github.com/MickLesk) ([#12130](https://github.com/community-scripts/ProxmoxVE/pull/12130))
- PLANKA: fix msg's [@danielalanbates](https://github.com/danielalanbates) ([#12143](https://github.com/community-scripts/ProxmoxVE/pull/12143))
### 🌐 Website
- #### 📝 Script Information
- MediaManager: Update documentation URL [@tremor021](https://github.com/tremor021) ([#12154](https://github.com/community-scripts/ProxmoxVE/pull/12154))
## 2026-02-20
### 🆕 New Scripts
- Sure ([#12114](https://github.com/community-scripts/ProxmoxVE/pull/12114))
- Calibre-Web ([#12115](https://github.com/community-scripts/ProxmoxVE/pull/12115))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Zammad: fix Elasticsearch JVM config and add daemon-reload [@MickLesk](https://github.com/MickLesk) ([#12125](https://github.com/community-scripts/ProxmoxVE/pull/12125))
- Huntarr: add build-essential for native pip dependencies [@MickLesk](https://github.com/MickLesk) ([#12126](https://github.com/community-scripts/ProxmoxVE/pull/12126))
- Dokploy: fix update function [@vhsdream](https://github.com/vhsdream) ([#12116](https://github.com/community-scripts/ProxmoxVE/pull/12116))
- #### 💥 Breaking Changes
- recyclarr: adjust paths for v8.0 breaking changes [@MickLesk](https://github.com/MickLesk) ([#12129](https://github.com/community-scripts/ProxmoxVE/pull/12129))
- #### 🔧 Refactor
- Planka: migrate data paths to new v2 directory structure [@MickLesk](https://github.com/MickLesk) ([#12128](https://github.com/community-scripts/ProxmoxVE/pull/12128))
### 🌐 Website
- #### 📝 Script Information
- fixen broken link to dawarich documentation [@RiX012](https://github.com/RiX012) ([#12103](https://github.com/community-scripts/ProxmoxVE/pull/12103))
## 2026-02-19
### 🆕 New Scripts
- TrueNAS-VM ([#12059](https://github.com/community-scripts/ProxmoxVE/pull/12059))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- add: patchmon breaking change msg [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12075](https://github.com/community-scripts/ProxmoxVE/pull/12075))
- LibreNMS: Various fixes [@tremor021](https://github.com/tremor021) ([#12089](https://github.com/community-scripts/ProxmoxVE/pull/12089))
### 🌐 Website
- #### 📝 Script Information
- truenas-vm: slug fix for source code link [@juronja](https://github.com/juronja) ([#12088](https://github.com/community-scripts/ProxmoxVE/pull/12088))
## 2026-02-18
### 🚀 Updated Scripts
- #### 💥 Breaking Changes
- [Fix] PatchMon: use `SERVER_PORT` in Nginx config if set in env [@vhsdream](https://github.com/vhsdream) ([#12053](https://github.com/community-scripts/ProxmoxVE/pull/12053))
### 💾 Core
- #### ✨ New Features
- core: Execution ID & Telemetry Improvements [@MickLesk](https://github.com/MickLesk) ([#12041](https://github.com/community-scripts/ProxmoxVE/pull/12041))
## 2026-02-17
### 🆕 New Scripts
- Databasus ([#12018](https://github.com/community-scripts/ProxmoxVE/pull/12018))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- [Hotfix] Cleanuparr: backup config before update [@vhsdream](https://github.com/vhsdream) ([#12039](https://github.com/community-scripts/ProxmoxVE/pull/12039))
- fix: pterodactyl-panel add symlink [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11997](https://github.com/community-scripts/ProxmoxVE/pull/11997))
### 💾 Core
- #### 🐞 Bug Fixes
- core: call get_lxc_ip in start() before updates [@MickLesk](https://github.com/MickLesk) ([#12015](https://github.com/community-scripts/ProxmoxVE/pull/12015))
- #### ✨ New Features
- tools/pve: add data analytics / formatting / linting [@MickLesk](https://github.com/MickLesk) ([#12034](https://github.com/community-scripts/ProxmoxVE/pull/12034))
- core: smart recovery for failed installs | extend exit_codes [@MickLesk](https://github.com/MickLesk) ([#11221](https://github.com/community-scripts/ProxmoxVE/pull/11221))
- #### 🔧 Refactor
- core: error-handler improvements | better exit_code handling | better tools.func source check [@MickLesk](https://github.com/MickLesk) ([#12019](https://github.com/community-scripts/ProxmoxVE/pull/12019))
### 🧰 Tools
- #### 🔧 Refactor
- Immich Public Proxy: centralize and fix systemd service creation [@MickLesk](https://github.com/MickLesk) ([#12025](https://github.com/community-scripts/ProxmoxVE/pull/12025))
### 📚 Documentation
- fix contribution/setup-fork [@andreasabeck](https://github.com/andreasabeck) ([#12047](https://github.com/community-scripts/ProxmoxVE/pull/12047))
## 2026-02-16
### 🆕 New Scripts
- RomM ([#11987](https://github.com/community-scripts/ProxmoxVE/pull/11987))
- LinkDing ([#11976](https://github.com/community-scripts/ProxmoxVE/pull/11976))
### 🚀 Updated Scripts
- Opencloud: Pin version to 5.1.0 [@vhsdream](https://github.com/vhsdream) ([#12004](https://github.com/community-scripts/ProxmoxVE/pull/12004))
- #### 🐞 Bug Fixes
- Tududi: Fix sed command for DB_FILE configuration [@tremor021](https://github.com/tremor021) ([#11988](https://github.com/community-scripts/ProxmoxVE/pull/11988))
- slskd: fix exit position [@MickLesk](https://github.com/MickLesk) ([#11963](https://github.com/community-scripts/ProxmoxVE/pull/11963))
- cryptpad: restore config earlier and run onlyoffice upgrade [@MickLesk](https://github.com/MickLesk) ([#11964](https://github.com/community-scripts/ProxmoxVE/pull/11964))
- jellyseerr/overseerr: Migrate update script to Seerr; prompt rerun [@MickLesk](https://github.com/MickLesk) ([#11965](https://github.com/community-scripts/ProxmoxVE/pull/11965))
- #### 🔧 Refactor
- core/vm's: ensure script state is sent on script exit [@MickLesk](https://github.com/MickLesk) ([#11991](https://github.com/community-scripts/ProxmoxVE/pull/11991))
- Vaultwarden: export VW_VERSION as version number [@MickLesk](https://github.com/MickLesk) ([#11966](https://github.com/community-scripts/ProxmoxVE/pull/11966))
- Zabbix: Improve zabbix-agent service detection [@MickLesk](https://github.com/MickLesk) ([#11968](https://github.com/community-scripts/ProxmoxVE/pull/11968))
### 💾 Core
- #### ✨ New Features
- tools.func: ensure /usr/local/bin PATH persists for pct enter sessions [@MickLesk](https://github.com/MickLesk) ([#11970](https://github.com/community-scripts/ProxmoxVE/pull/11970))
- #### 🔧 Refactor
- core: remove duplicate error handler from alpine-install.func [@MickLesk](https://github.com/MickLesk) ([#11971](https://github.com/community-scripts/ProxmoxVE/pull/11971))
### 📂 Github
- github: add "website" label if "json" changed [@MickLesk](https://github.com/MickLesk) ([#11975](https://github.com/community-scripts/ProxmoxVE/pull/11975))
### 🌐 Website
- #### 📝 Script Information
- Update Wishlist LXC webpage to include reverse proxy info [@summoningpixels](https://github.com/summoningpixels) ([#11973](https://github.com/community-scripts/ProxmoxVE/pull/11973))
- Update OpenCloud LXC webpage to include services ports [@summoningpixels](https://github.com/summoningpixels) ([#11969](https://github.com/community-scripts/ProxmoxVE/pull/11969))
## 2026-02-15
### 🆕 New Scripts
- ebusd ([#11942](https://github.com/community-scripts/ProxmoxVE/pull/11942))
- add: seer script and migrations [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11930](https://github.com/community-scripts/ProxmoxVE/pull/11930))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Fix seerr URL in jellyseerr script [@lucacome](https://github.com/lucacome) ([#11951](https://github.com/community-scripts/ProxmoxVE/pull/11951))
- Fix jellyseer and overseer script replacement [@lucacome](https://github.com/lucacome) ([#11949](https://github.com/community-scripts/ProxmoxVE/pull/11949))
- Tautulli: Add setuptools < 81 [@tremor021](https://github.com/tremor021) ([#11943](https://github.com/community-scripts/ProxmoxVE/pull/11943))
- #### 💥 Breaking Changes
- Refactor: Patchmon [@vhsdream](https://github.com/vhsdream) ([#11888](https://github.com/community-scripts/ProxmoxVE/pull/11888))
## 2026-02-14
### 🚀 Updated Scripts

View File

@@ -18,6 +18,9 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details>
<summary><h2>📜 History</h2></summary>
@@ -27,7 +30,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details>
<summary><h4>February (14 entries)</h4></summary>
<summary><h4>February (21 entries)</h4></summary>
[View February 2026 Changelog](.github/changelogs/2026/02.md)
@@ -404,8 +407,119 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-02-23
### 🆕 New Scripts
- 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
- core: Enhance signal handling, reported "status" and logs [@MickLesk](https://github.com/MickLesk) ([#12216](https://github.com/community-scripts/ProxmoxVE/pull/12216))
### 💾 Core
- #### 🔧 Refactor
- core: Improve error handling and logging for LXC builds [@MickLesk](https://github.com/MickLesk) ([#12208](https://github.com/community-scripts/ProxmoxVE/pull/12208))
### 🌐 Website
- #### 🐞 Bug Fixes
- calibre-web: update default credentials [@LaevaertK](https://github.com/LaevaertK) ([#12201](https://github.com/community-scripts/ProxmoxVE/pull/12201))
- #### 📝 Script Information
- chore: update Frigate documentation and website URLs [@JohnICB](https://github.com/JohnICB) ([#12218](https://github.com/community-scripts/ProxmoxVE/pull/12218))
## 2026-02-22
### 🆕 New Scripts
- Gramps-Web ([#12157](https://github.com/community-scripts/ProxmoxVE/pull/12157))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: Apache Guacamole - bump to Temurin JDK 17 to resolve Debian 13 (Trixie) install failure [@Copilot](https://github.com/Copilot) ([#12161](https://github.com/community-scripts/ProxmoxVE/pull/12161))
- Docker-VM: add error handling for virt-customize finalization [@MickLesk](https://github.com/MickLesk) ([#12127](https://github.com/community-scripts/ProxmoxVE/pull/12127))
- [Fix] Sure: add Sidekiq service [@vhsdream](https://github.com/vhsdream) ([#12186](https://github.com/community-scripts/ProxmoxVE/pull/12186))
- #### ✨ New Features
- Refactor & Bump to v2: Plex [@MickLesk](https://github.com/MickLesk) ([#12179](https://github.com/community-scripts/ProxmoxVE/pull/12179))
- #### 🔧 Refactor
- karakeep: bump to node 24 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12183](https://github.com/community-scripts/ProxmoxVE/pull/12183))
### 💾 Core
- #### ✨ New Features
- tools.func: add GitHub API rate-limit detection and GITHUB_TOKEN support [@MickLesk](https://github.com/MickLesk) ([#12176](https://github.com/community-scripts/ProxmoxVE/pull/12176))
### 🧰 Tools
- CR*NMASTER ([#12065](https://github.com/community-scripts/ProxmoxVE/pull/12065))
- #### 🔧 Refactor
- Update package management commands in clean-lxcs.sh [@heinemannj](https://github.com/heinemannj) ([#12166](https://github.com/community-scripts/ProxmoxVE/pull/12166))
### ❔ Uncategorized
- calibre-web: Update logo URL [@MickLesk](https://github.com/MickLesk) ([#12178](https://github.com/community-scripts/ProxmoxVE/pull/12178))
## 2026-02-21
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Pangolin: restore config before db migration, use drizzle-kit push [@MickLesk](https://github.com/MickLesk) ([#12130](https://github.com/community-scripts/ProxmoxVE/pull/12130))
- PLANKA: fix msg's [@danielalanbates](https://github.com/danielalanbates) ([#12143](https://github.com/community-scripts/ProxmoxVE/pull/12143))
### 🌐 Website
- #### 📝 Script Information
- MediaManager: Update documentation URL [@tremor021](https://github.com/tremor021) ([#12154](https://github.com/community-scripts/ProxmoxVE/pull/12154))
## 2026-02-20
### 🆕 New Scripts
- Sure ([#12114](https://github.com/community-scripts/ProxmoxVE/pull/12114))
- Calibre-Web ([#12115](https://github.com/community-scripts/ProxmoxVE/pull/12115))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Zammad: fix Elasticsearch JVM config and add daemon-reload [@MickLesk](https://github.com/MickLesk) ([#12125](https://github.com/community-scripts/ProxmoxVE/pull/12125))
- Huntarr: add build-essential for native pip dependencies [@MickLesk](https://github.com/MickLesk) ([#12126](https://github.com/community-scripts/ProxmoxVE/pull/12126))
- Dokploy: fix update function [@vhsdream](https://github.com/vhsdream) ([#12116](https://github.com/community-scripts/ProxmoxVE/pull/12116))
- #### 💥 Breaking Changes
- recyclarr: adjust paths for v8.0 breaking changes [@MickLesk](https://github.com/MickLesk) ([#12129](https://github.com/community-scripts/ProxmoxVE/pull/12129))
- #### 🔧 Refactor
- Planka: migrate data paths to new v2 directory structure [@MickLesk](https://github.com/MickLesk) ([#12128](https://github.com/community-scripts/ProxmoxVE/pull/12128))
### 🌐 Website
- #### 📝 Script Information
- fixen broken link to dawarich documentation [@RiX012](https://github.com/RiX012) ([#12103](https://github.com/community-scripts/ProxmoxVE/pull/12103))
## 2026-02-19
### 🆕 New Scripts
@@ -1286,210 +1400,4 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### ✨ New Features
- core: add IPv6 fallback support to get_current_ip functions | add check for SSH_KEYS_FILE in user_defaults [@MickLesk](https://github.com/MickLesk) ([#11067](https://github.com/community-scripts/ProxmoxVE/pull/11067))
## 2026-01-22
### 🆕 New Scripts
- Loki | Alpine-Loki ([#11048](https://github.com/community-scripts/ProxmoxVE/pull/11048))
### 🚀 Updated Scripts
- Immich: Increase RAM to 6GB [@vhsdream](https://github.com/vhsdream) ([#10965](https://github.com/community-scripts/ProxmoxVE/pull/10965))
- #### 🐞 Bug Fixes
- Jotty: Increase default disk size from 6 to 8 [@tremor021](https://github.com/tremor021) ([#11056](https://github.com/community-scripts/ProxmoxVE/pull/11056))
- Fix tags in several scripts [@s4dmach1ne](https://github.com/s4dmach1ne) ([#11050](https://github.com/community-scripts/ProxmoxVE/pull/11050))
### 💾 Core
- #### ✨ New Features
- tools: use distro packages for MariaDB by default [@MickLesk](https://github.com/MickLesk) ([#11049](https://github.com/community-scripts/ProxmoxVE/pull/11049))
## 2026-01-21
### 🆕 New Scripts
- Byparr ([#11039](https://github.com/community-scripts/ProxmoxVE/pull/11039))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: Snipe-IT update missing all user uploads (#11032) [@ruanmed](https://github.com/ruanmed) ([#11033](https://github.com/community-scripts/ProxmoxVE/pull/11033))
- yubal: fix for v0.2 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11006](https://github.com/community-scripts/ProxmoxVE/pull/11006))
- Joplin-Server: use yarn workspaces focus for faster builds [@MickLesk](https://github.com/MickLesk) ([#11027](https://github.com/community-scripts/ProxmoxVE/pull/11027))
### 💾 Core
- #### ✨ New Features
- tools: add ubuntu PHP repository setup [@MickLesk](https://github.com/MickLesk) ([#11034](https://github.com/community-scripts/ProxmoxVE/pull/11034))
- #### 🔧 Refactor
- core: allow empty tags & improve template search [@MickLesk](https://github.com/MickLesk) ([#11020](https://github.com/community-scripts/ProxmoxVE/pull/11020))
### 🌐 Website
- #### 📝 Script Information
- Joplin Server: Set disable flag to true in joplin-server.json [@tremor021](https://github.com/tremor021) ([#11008](https://github.com/community-scripts/ProxmoxVE/pull/11008))
## 2026-01-20
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- dolibarr: switch mirror [@MickLesk](https://github.com/MickLesk) ([#11004](https://github.com/community-scripts/ProxmoxVE/pull/11004))
- checkmk: reordner base function [@MickLesk](https://github.com/MickLesk) ([#10990](https://github.com/community-scripts/ProxmoxVE/pull/10990))
- Homepage: preserve config directory during updates [@MickLesk](https://github.com/MickLesk) ([#10993](https://github.com/community-scripts/ProxmoxVE/pull/10993))
- DiscoPanel: add go for update build process [@miausalvaje](https://github.com/miausalvaje) ([#10991](https://github.com/community-scripts/ProxmoxVE/pull/10991))
### 💾 Core
- #### ✨ New Features
- core: add retry logic for template lock in LXC container creation [@MickLesk](https://github.com/MickLesk) ([#11002](https://github.com/community-scripts/ProxmoxVE/pull/11002))
- core: implement ensure_profile_loaded function [@MickLesk](https://github.com/MickLesk) ([#10999](https://github.com/community-scripts/ProxmoxVE/pull/10999))
- core: add input validations for several functions [@MickLesk](https://github.com/MickLesk) ([#10995](https://github.com/community-scripts/ProxmoxVE/pull/10995))
## 2026-01-19
### 🆕 New Scripts
- yubal ([#10955](https://github.com/community-scripts/ProxmoxVE/pull/10955))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Apache-Guacamole: move jdbc cleanup after schema upgrade [@MickLesk](https://github.com/MickLesk) ([#10974](https://github.com/community-scripts/ProxmoxVE/pull/10974))
- Outline: prevent corepack interactive prompt blocking installation [@MickLesk](https://github.com/MickLesk) ([#10973](https://github.com/community-scripts/ProxmoxVE/pull/10973))
- firefly: prevent nested storage directories during update (#10967) [@MickLesk](https://github.com/MickLesk) ([#10972](https://github.com/community-scripts/ProxmoxVE/pull/10972))
- PeaNUT: change default port [@vhsdream](https://github.com/vhsdream) ([#10962](https://github.com/community-scripts/ProxmoxVE/pull/10962))
- Update/splunk enterprise [@rcastley](https://github.com/rcastley) ([#10949](https://github.com/community-scripts/ProxmoxVE/pull/10949))
- #### ✨ New Features
- Pangolin: use dynamic badger plugin version [@MickLesk](https://github.com/MickLesk) ([#10975](https://github.com/community-scripts/ProxmoxVE/pull/10975))
- Tautulli: add version detection and add proper update script [@MickLesk](https://github.com/MickLesk) ([#10976](https://github.com/community-scripts/ProxmoxVE/pull/10976))
- #### 🔧 Refactor
- Refactor: Remove custom IP fetching in scripts [@tremor021](https://github.com/tremor021) ([#10954](https://github.com/community-scripts/ProxmoxVE/pull/10954))
- Refactor: Homepage [@tremor021](https://github.com/tremor021) ([#10950](https://github.com/community-scripts/ProxmoxVE/pull/10950))
- Refactor: hev-socks5-server [@tremor021](https://github.com/tremor021) ([#10945](https://github.com/community-scripts/ProxmoxVE/pull/10945))
### 🗑️ Deleted Scripts
- Remove: phpIPAM [@MickLesk](https://github.com/MickLesk) ([#10939](https://github.com/community-scripts/ProxmoxVE/pull/10939))
### 💾 Core
- #### ✨ New Features
- core: add RFC 1123/952 compliant hostname/FQDN validation [@MickLesk](https://github.com/MickLesk) ([#10977](https://github.com/community-scripts/ProxmoxVE/pull/10977))
- [core]: Make LXC IP a global variable [@tremor021](https://github.com/tremor021) ([#10951](https://github.com/community-scripts/ProxmoxVE/pull/10951))
### 🧰 Tools
- #### 🔧 Refactor
- Refactor: copyparty [@MickLesk](https://github.com/MickLesk) ([#10941](https://github.com/community-scripts/ProxmoxVE/pull/10941))
## 2026-01-18
### 🆕 New Scripts
- Termix ([#10887](https://github.com/community-scripts/ProxmoxVE/pull/10887))
- ThingsBoard ([#10904](https://github.com/community-scripts/ProxmoxVE/pull/10904))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Fix Patchmon install script (escaping) [@christiaangoossens](https://github.com/christiaangoossens) ([#10920](https://github.com/community-scripts/ProxmoxVE/pull/10920))
- refactor: peanut entrypoint [@CrazyWolf13](https://github.com/CrazyWolf13) ([#10902](https://github.com/community-scripts/ProxmoxVE/pull/10902))
- #### 💥 Breaking Changes
- Update Patchmon default Nginx config (IPv6 and correct scheme) [@christiaangoossens](https://github.com/christiaangoossens) ([#10917](https://github.com/community-scripts/ProxmoxVE/pull/10917))
- #### 🔧 Refactor
- Refactor: FluidCalendar [@tremor021](https://github.com/tremor021) ([#10928](https://github.com/community-scripts/ProxmoxVE/pull/10928))
### 🗑️ Deleted Scripts
- Remove iVentoy script [@tremor021](https://github.com/tremor021) ([#10924](https://github.com/community-scripts/ProxmoxVE/pull/10924))
### 💾 Core
- #### ✨ New Features
- core: improve password handling and validation logic [@MickLesk](https://github.com/MickLesk) ([#10925](https://github.com/community-scripts/ProxmoxVE/pull/10925))
- #### 🔧 Refactor
- hwaccel: improve NVIDIA version matching and GPU selection UI [@MickLesk](https://github.com/MickLesk) ([#10901](https://github.com/community-scripts/ProxmoxVE/pull/10901))
### 📂 Github
- Fix typo in the New Script request template [@tremor021](https://github.com/tremor021) ([#10891](https://github.com/community-scripts/ProxmoxVE/pull/10891))
### 🌐 Website
- #### 🐞 Bug Fixes
- fix: preserve newest scripts pagination [@jgrubiox](https://github.com/jgrubiox) ([#10882](https://github.com/community-scripts/ProxmoxVE/pull/10882))
### ❔ Uncategorized
- Update qui.json [@GalaxyCatD3v](https://github.com/GalaxyCatD3v) ([#10896](https://github.com/community-scripts/ProxmoxVE/pull/10896))
## 2026-01-17
### 🆕 New Scripts
- TRIP ([#10864](https://github.com/community-scripts/ProxmoxVE/pull/10864))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix sonarqube update version info (#10870) [@Karlito83](https://github.com/Karlito83) ([#10871](https://github.com/community-scripts/ProxmoxVE/pull/10871))
- WGDashboard: Update repo URL [@tremor021](https://github.com/tremor021) ([#10872](https://github.com/community-scripts/ProxmoxVE/pull/10872))
### 🌐 Website
- #### 📝 Script Information
- Disable Palmer [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#10889](https://github.com/community-scripts/ProxmoxVE/pull/10889))
## 2026-01-16
### 🆕 New Scripts
- Flatnotes ([#10857](https://github.com/community-scripts/ProxmoxVE/pull/10857))
- Unifi OS Server ([#10856](https://github.com/community-scripts/ProxmoxVE/pull/10856))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Jotty: increase RAM; cap heap size at 3GB during build [@vhsdream](https://github.com/vhsdream) ([#10868](https://github.com/community-scripts/ProxmoxVE/pull/10868))
- SnowShare: Increase default resources [@TuroYT](https://github.com/TuroYT) ([#10865](https://github.com/community-scripts/ProxmoxVE/pull/10865))
- postgresql: name of sources file fixed (update check) [@JamborJan](https://github.com/JamborJan) ([#10854](https://github.com/community-scripts/ProxmoxVE/pull/10854))
- immich: use dpkg-query to get intel-opencl-icd version [@MickLesk](https://github.com/MickLesk) ([#10848](https://github.com/community-scripts/ProxmoxVE/pull/10848))
- domain-monitor: fix: cron user [@CrazyWolf13](https://github.com/CrazyWolf13) ([#10846](https://github.com/community-scripts/ProxmoxVE/pull/10846))
- pihole/unbound: create unbound config before apt install to prevent port conflicts [@MickLesk](https://github.com/MickLesk) ([#10839](https://github.com/community-scripts/ProxmoxVE/pull/10839))
- zammad: use ln -sf to avoid failure when symlink exists [@MickLesk](https://github.com/MickLesk) ([#10840](https://github.com/community-scripts/ProxmoxVE/pull/10840))
### ❔ Uncategorized
- qui: fix: category [@CrazyWolf13](https://github.com/CrazyWolf13) ([#10847](https://github.com/community-scripts/ProxmoxVE/pull/10847))
- core: add IPv6 fallback support to get_current_ip functions | add check for SSH_KEYS_FILE in user_defaults [@MickLesk](https://github.com/MickLesk) ([#11067](https://github.com/community-scripts/ProxmoxVE/pull/11067))

View File

@@ -51,7 +51,7 @@ function update_script() {
exit
fi
JAVA_VERSION="11" setup_java
JAVA_VERSION="17" setup_java
msg_info "Stopping Services"
systemctl stop guacd tomcat

73
ct/calibre-web.sh Normal file
View 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: mikolaj92
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/janeczku/calibre-web
APP="calibre-web"
var_tags="${var_tags:-media;books}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-8}"
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/calibre-web ]]; then
msg_error "No Calibre-Web Installation Found!"
exit
fi
if check_for_gh_release "Calibre-Web" "janeczku/calibre-web"; then
msg_info "Stopping Service"
systemctl stop calibre-web
msg_ok "Stopped Service"
msg_info "Backing up Data"
cp -r /opt/calibre-web/app.db /opt/app.db_backup
cp -r /opt/calibre-web/data /opt/data_backup
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Calibre-Web" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibre-web*.tar.gz"
setup_uv
msg_info "Installing Dependencies"
cd /opt/calibre-web
$STD uv venv
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir --upgrade pip setuptools wheel
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir -r requirements.txt
msg_ok "Installed Dependencies"
msg_info "Restoring Data"
cp /opt/app.db_backup /opt/calibre-web/app.db 2>/dev/null
cp -r /opt/data_backup /opt/calibre-web/data 2>/dev/null
rm -rf /opt/app.db_backup /opt/data_backup
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start calibre-web
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}:8083${CL}"

View File

@@ -30,7 +30,7 @@ function update_script() {
fi
msg_info "Updating Dokploy"
$STD bash <(curl -sSL https://dokploy.com/install.sh)
curl -sSL https://dokploy.com/install.sh | $STD bash -s update
msg_ok "Updated Dokploy"
msg_ok "Updated successfully!"
exit

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Authors: tteck (tteckster)
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ) | Co-Author: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/
@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-11}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-0}"
var_gpu="${var_gpu:-yes}"
@@ -21,15 +21,15 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/frigate.service ]]; then
msg_error "No ${APP} Installation Found!"
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/frigate.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "To update Frigate, create a new container and transfer your configuration."
exit
fi
msg_error "To update Frigate, create a new container and transfer your configuration."
exit
}
start

93
ct/gramps-web.sh Normal file
View File

@@ -0,0 +1,93 @@
#!/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://www.grampsweb.org/
APP="gramps-web"
var_tags="${var_tags:-genealogy;family;collaboration}"
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_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/gramps-web-api ]] || [[ ! -d /opt/gramps-web/frontend ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
PYTHON_VERSION="3.12" setup_uv
NODE_VERSION="22" setup_nodejs
if check_for_gh_release "gramps-web-api" "gramps-project/gramps-web-api"; then
msg_info "Stopping Service"
systemctl stop gramps-web
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gramps-web-api" "gramps-project/gramps-web-api" "tarball" "latest" "/opt/gramps-web-api"
msg_info "Updating Gramps Web API"
$STD uv venv -c -p python3.12 /opt/gramps-web/venv
source /opt/gramps-web/venv/bin/activate
$STD uv pip install --no-cache-dir --upgrade pip setuptools wheel
$STD uv pip install --no-cache-dir gunicorn
$STD uv pip install --no-cache-dir /opt/gramps-web-api
msg_ok "Updated Gramps Web API"
msg_info "Applying Database Migration"
cd /opt/gramps-web-api
GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \
ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \
GRAMPSHOME=/opt/gramps-web/data/gramps \
GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \
$STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate
msg_ok "Applied Database Migration"
msg_info "Starting Service"
systemctl start gramps-web
msg_ok "Started Service"
fi
if check_for_gh_release "gramps-web" "gramps-project/gramps-web"; then
msg_info "Stopping Service"
systemctl stop gramps-web
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gramps-web" "gramps-project/gramps-web" "tarball" "latest" "/opt/gramps-web/frontend"
msg_info "Updating Gramps Web Frontend"
cd /opt/gramps-web/frontend
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
$STD corepack enable
$STD npm install
$STD npm run build
msg_ok "Updated Gramps Web Frontend"
msg_info "Starting Service"
systemctl start gramps-web
msg_ok "Started Service"
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}:5000${CL}"

6
ct/headers/calibre-web Normal file
View File

@@ -0,0 +1,6 @@
___ __ __
_________ _/ (_) /_ ________ _ _____ / /_
/ ___/ __ `/ / / __ \/ ___/ _ \_____| | /| / / _ \/ __ \
/ /__/ /_/ / / / /_/ / / / __/_____/ |/ |/ / __/ /_/ /
\___/\__,_/_/_/_.___/_/ \___/ |__/|__/\___/_.___/

6
ct/headers/gramps-web Normal file
View File

@@ -0,0 +1,6 @@
__
____ __________ _____ ___ ____ _____ _ _____ / /_
/ __ `/ ___/ __ `/ __ `__ \/ __ \/ ___/____| | /| / / _ \/ __ \
/ /_/ / / / /_/ / / / / / / /_/ (__ )_____/ |/ |/ / __/ /_/ /
\__, /_/ \__,_/_/ /_/ /_/ .___/____/ |__/|__/\___/_.___/
/____/ /_/

6
ct/headers/sparkyfitness Normal file
View File

@@ -0,0 +1,6 @@
_____ __ _______ __
/ ___/____ ____ ______/ /____ __/ ____(_) /_____ ___ __________
\__ \/ __ \/ __ `/ ___/ //_/ / / / /_ / / __/ __ \/ _ \/ ___/ ___/
___/ / /_/ / /_/ / / / ,< / /_/ / __/ / / /_/ / / / __(__ |__ )
/____/ .___/\__,_/_/ /_/|_|\__, /_/ /_/\__/_/ /_/\___/____/____/
/_/ /____/

6
ct/headers/sure Normal file
View File

@@ -0,0 +1,6 @@
_____
/ ___/__ __________
\__ \/ / / / ___/ _ \
___/ / /_/ / / / __/
/____/\__,_/_/ \___/

View File

@@ -1,61 +0,0 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: BiluliB
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/plexguide/Huntarr.io
APP="huntarr"
var_tags="${var_tags:-arr}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_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/huntarr/main.py ]]; 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
msg_info "Stopping Service"
systemctl stop huntarr
msg_ok "Stopped Service"
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"
msg_info "Starting Service"
systemctl start huntarr
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}:9705${CL}"

View File

@@ -60,7 +60,7 @@ function update_script() {
$STD corepack disable
fi
MODULE_VERSION="$(jq -r '.packageManager | split("@")[1]' /opt/karakeep/package.json)"
NODE_VERSION="22" NODE_MODULE="pnpm@${MODULE_VERSION}" setup_nodejs
NODE_VERSION="24" NODE_MODULE="pnpm@${MODULE_VERSION}" setup_nodejs
setup_meilisearch
msg_info "Updating Karakeep"

View File

@@ -51,7 +51,6 @@ function update_script() {
$STD npm run db:generate
$STD npm run build
$STD npm run build:cli
$STD npm run db:push
cp -R .next/standalone ./
chmod +x ./dist/cli.mjs
cp server/db/names.json ./dist/names.json
@@ -64,6 +63,11 @@ function update_script() {
rm -f /opt/pangolin_config_backup.tar.gz
msg_ok "Restored config"
msg_info "Running database migrations"
cd /opt/pangolin
ENVIRONMENT=prod $STD npx drizzle-kit push --config drizzle.sqlite.config.ts
msg_ok "Ran database migrations"
msg_info "Updating Badger plugin version"
BADGER_VERSION=$(get_latest_github_release "fosrl/badger" "false")
sed -i "s/version: \"v[0-9.]*\"/version: \"$BADGER_VERSION\"/g" /opt/pangolin/config/traefik/traefik_config.yml

View File

@@ -31,16 +31,24 @@ function update_script() {
if check_for_gh_release "planka" "plankanban/planka"; then
msg_info "Stopping Service"
systemctl stop planka
msg_info "Stopped Service"
msg_ok "Stopped Service"
msg_info "Backing up data"
BK="/opt/planka-backup"
mkdir -p "$BK"/{favicons,user-avatars,background-images,attachments}
[ -f /opt/planka/.env ] && mv /opt/planka/.env "$BK"/
[ -d /opt/planka/public/favicons ] && cp -a /opt/planka/public/favicons/. "$BK/favicons/"
[ -d /opt/planka/public/user-avatars ] && cp -a /opt/planka/public/user-avatars/. "$BK/user-avatars/"
[ -d /opt/planka/public/background-images ] && cp -a /opt/planka/public/background-images/. "$BK/background-images/"
[ -d /opt/planka/private/attachments ] && cp -a /opt/planka/private/attachments/. "$BK/attachments/"
# Support both old (pre-v2) and new (v2) directory layouts
if [ -d /opt/planka/data/protected ]; then
[ -d /opt/planka/data/protected/favicons ] && cp -a /opt/planka/data/protected/favicons/. "$BK/favicons/"
[ -d /opt/planka/data/protected/user-avatars ] && cp -a /opt/planka/data/protected/user-avatars/. "$BK/user-avatars/"
[ -d /opt/planka/data/protected/background-images ] && cp -a /opt/planka/data/protected/background-images/. "$BK/background-images/"
[ -d /opt/planka/data/private/attachments ] && cp -a /opt/planka/data/private/attachments/. "$BK/attachments/"
else
[ -d /opt/planka/public/favicons ] && cp -a /opt/planka/public/favicons/. "$BK/favicons/"
[ -d /opt/planka/public/user-avatars ] && cp -a /opt/planka/public/user-avatars/. "$BK/user-avatars/"
[ -d /opt/planka/public/background-images ] && cp -a /opt/planka/public/background-images/. "$BK/background-images/"
[ -d /opt/planka/private/attachments ] && cp -a /opt/planka/private/attachments/. "$BK/attachments/"
fi
rm -rf /opt/planka
msg_ok "Backed up data"
@@ -53,15 +61,16 @@ function update_script() {
msg_info "Restoring data"
[ -f "$BK/.env" ] && mv "$BK/.env" /opt/planka/.env
mkdir -p /opt/planka/public/{favicons,user-avatars,background-images} /opt/planka/private/attachments
[ -d "$BK/favicons" ] && cp -a "$BK/favicons/." /opt/planka/public/favicons/
[ -d "$BK/user-avatars" ] && cp -a "$BK/user-avatars/." /opt/planka/public/user-avatars/
[ -d "$BK/background-images" ] && cp -a "$BK/background-images/." /opt/planka/public/background-images/
[ -d "$BK/attachments" ] && cp -a "$BK/attachments/." /opt/planka/private/attachments/
# Planka v2 uses unified data directory structure
mkdir -p /opt/planka/data/protected/{favicons,user-avatars,background-images} /opt/planka/data/private/attachments
[ -d "$BK/favicons" ] && cp -a "$BK/favicons/." /opt/planka/data/protected/favicons/
[ -d "$BK/user-avatars" ] && cp -a "$BK/user-avatars/." /opt/planka/data/protected/user-avatars/
[ -d "$BK/background-images" ] && cp -a "$BK/background-images/." /opt/planka/data/protected/background-images/
[ -d "$BK/attachments" ] && cp -a "$BK/attachments/." /opt/planka/data/private/attachments/
rm -rf "$BK"
msg_ok "Restored data"
msg_ok "Migrate Database"
msg_info "Migrate Database"
cd /opt/planka
$STD npm run db:upgrade
$STD npm run db:migrate

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.plex.tv/
@@ -24,28 +24,54 @@ function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] &&
[[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
if ! dpkg -l plexmediaserver &>/dev/null; then
msg_error "No ${APP} Installation Found!"
exit
fi
UPD=$(msg_menu "Plex Update Options" \
"1" "Update LXC" \
"2" "Install plexupdate")
if [ "$UPD" == "1" ]; then
msg_info "Updating ${APP} LXC"
$STD apt update
$STD apt -y upgrade
msg_ok "Updated ${APP} LXC"
msg_ok "Updated successfully!"
exit
# Migrate from old repository to new one if needed
if [[ -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
local current_uri
current_uri=$(grep -oP '(?<=URIs: ).*' /etc/apt/sources.list.d/plexmediaserver.sources 2>/dev/null || true)
if [[ "$current_uri" == *"downloads.plex.tv/repo/deb"* ]]; then
msg_info "Migrating to new Plex repository"
rm -f /etc/apt/sources.list.d/plexmediaserver.sources
rm -f /usr/share/keyrings/PlexSign.asc
setup_deb822_repo \
"plexmediaserver" \
"https://downloads.plex.tv/plex-keys/PlexSign.v2.key" \
"https://repo.plex.tv/deb/" \
"public" \
"main"
msg_ok "Migrated to new Plex repository"
fi
elif [[ -f /etc/apt/sources.list.d/plexmediaserver.list ]]; then
msg_info "Migrating to new Plex repository (deb822)"
rm -f /etc/apt/sources.list.d/plexmediaserver.list
rm -f /etc/apt/sources.list.d/plex*
rm -f /usr/share/keyrings/PlexSign.asc
setup_deb822_repo \
"plexmediaserver" \
"https://downloads.plex.tv/plex-keys/PlexSign.v2.key" \
"https://repo.plex.tv/deb/" \
"public" \
"main"
msg_ok "Migrated to new Plex repository (deb822)"
fi
if [ "$UPD" == "2" ]; then
set +e
bash -c "$(curl -fsSL https://raw.githubusercontent.com/mrworf/plexupdate/master/extras/installer.sh)"
msg_ok "Updated successfully!"
exit
if [[ -f /usr/local/bin/plexupdate ]] || [[ -d /opt/plexupdate ]]; then
msg_info "Removing legacy plexupdate"
rm -rf /opt/plexupdate /usr/local/bin/plexupdate
crontab -l 2>/dev/null | grep -v plexupdate | crontab - 2>/dev/null || true
msg_ok "Removed legacy plexupdate"
fi
msg_info "Updating Plex Media Server"
$STD apt update
$STD apt install -y plexmediaserver
msg_ok "Updated Plex Media Server"
msg_ok "Updated successfully!"
exit
}
start

View File

@@ -23,7 +23,7 @@ function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /root/.config/recyclarr/recyclarr.yml ]]; then
if [[ ! -f /root/.config/recyclarr/recyclarr.yml ]] && [[ ! -d /root/.config/recyclarr/configs ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
@@ -33,6 +33,20 @@ function update_script() {
fetch_and_deploy_gh_release "recyclarr" "recyclarr/recyclarr" "prebuild" "latest" "/usr/local/bin" "recyclarr-linux-x64.tar.xz"
# Migrate includes from configs/ to includes/ (recyclarr v8)
RECYCLARR_DIR="/root/.config/recyclarr"
mkdir -p "$RECYCLARR_DIR/includes"
if [[ -d "$RECYCLARR_DIR/configs" ]]; then
for item in "$RECYCLARR_DIR/configs"/*/; do
[[ -d "$item" ]] || continue
dir_name=$(basename "$item")
# Only move subdirs that look like include dirs (not the configs themselves)
if [[ "$dir_name" != "configs" ]] && [[ ! -d "$RECYCLARR_DIR/includes/$dir_name" ]]; then
mv "$item" "$RECYCLARR_DIR/includes/"
fi
done
fi
msg_ok "Updated successfully!"
fi
exit

83
ct/sparkyfitness.sh Normal file
View File

@@ -0,0 +1,83 @@
#!/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: Tom Frenzel (tomfrenzel)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/CodeWithCJ/SparkyFitness
APP="SparkyFitness"
var_tags="${var_tags:-health;fitness}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
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/sparkyfitness ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
NODE_VERSION="25" setup_nodejs
if check_for_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness"; then
msg_info "Stopping Services"
systemctl stop sparkyfitness-server nginx
msg_ok "Stopped Services"
msg_info "Backing up data"
mkdir -p /opt/sparkyfitness_backup
if [[ -d /opt/sparkyfitness/SparkyFitnessServer/uploads ]]; then
cp -r /opt/sparkyfitness/SparkyFitnessServer/uploads /opt/sparkyfitness_backup/
fi
if [[ -d /opt/sparkyfitness/SparkyFitnessServer/backup ]]; then
cp -r /opt/sparkyfitness/SparkyFitnessServer/backup /opt/sparkyfitness_backup/
fi
msg_ok "Backed up data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness" "tarball"
msg_info "Updating Sparky Fitness Backend"
cd /opt/sparkyfitness/SparkyFitnessServer
$STD npm install
msg_ok "Updated Sparky Fitness Backend"
msg_info "Updating Sparky Fitness Frontend (Patience)"
cd /opt/sparkyfitness/SparkyFitnessFrontend
$STD npm install
$STD npm run build
cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/
msg_ok "Updated Sparky Fitness Frontend"
msg_info "Restoring data"
cp -r /opt/sparkyfitness_backup/. /opt/sparkyfitness/SparkyFitnessServer/
rm -rf /opt/sparkyfitness_backup
msg_ok "Restored data"
msg_info "Starting Services"
$STD systemctl start sparkyfitness-server nginx
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

97
ct/sure.sh Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://sure.am
APP="Sure"
var_tags="${var_tags:-finance}"
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_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/sure ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "Sure" "we-promise/sure"; then
if [[ ! -f /etc/systemd/system/sure-worker.service ]]; then
cat <<EOF >/etc/systemd/system/sure-worker.service
[Unit]
Description=Sure Background Worker (Sidekiq)
After=network.target redis-server.service
[Service]
Type=simple
WorkingDirectory=/opt/sure
Environment=RAILS_ENV=production
Environment=BUNDLE_DEPLOYMENT=1
Environment=BUNDLE_WITHOUT=development
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/bin:/usr/local/bin:/sbin:/bin
EnvironmentFile=/etc/sure/.env
ExecStart=/opt/sure/bin/bundle exec sidekiq -e production
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q sure-worker
msg_info "Stopping Service"
$STD systemctl stop sure
msg_ok "Stopped Service"
else
msg_info "Stopping services"
$STD systemctl stop sure-worker sure
msg_ok "Stopped services"
fi
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Sure" "we-promise/sure" "tarball" "latest" "/opt/sure"
RUBY_VERSION="$(cat /opt/sure/.ruby-version)" RUBY_INSTALL_RAILS=false setup_ruby
msg_info "Updating Sure"
source ~/.profile
cd /opt/sure
export RAILS_ENV=production
export BUNDLE_DEPLOYMENT=1
export BUNDLE_WITHOUT=development
$STD ./bin/bundle install
$STD ./bin/bundle exec bootsnap precompile --gemfile -j 0
$STD ./bin/bundle exec bootsnap precompile -j 0 app/ lib/
export SECRET_KEY_BASE_DUMMY=1 && $STD ./bin/rails assets:precompile
unset SECRET_KEY_BASE_DUMMY
msg_ok "Updated Sure"
msg_info "Starting Services"
$STD systemctl start sure sure-worker
msg_ok "Started Services"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
msg_ok "Completed successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

View File

@@ -0,0 +1,40 @@
{
"name": "Calibre-Web",
"slug": "calibre-web",
"categories": [
4
],
"date_created": "2026-02-20",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8083,
"documentation": "https://github.com/janeczku/calibre-web/wiki",
"website": "https://github.com/janeczku/calibre-web",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/calibre-web.webp",
"config_path": "/opt/calibre-web/app.db",
"description": "Web app for browsing, reading and downloading eBooks from a Calibre database. Provides an attractive interface with mobile support, user management, and eBook conversion capabilities.",
"install_methods": [
{
"type": "default",
"script": "ct/calibre-web.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": "admin",
"password": "admin123"
},
"notes": [
{
"text": "Upload your Calibre library metadata.db during first setup wizard.",
"type": "info"
}
]
}

View File

@@ -0,0 +1,44 @@
{
"name": "CR*NMASTER",
"slug": "cronmaster",
"categories": [
1
],
"date_created": "2026-02-22",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/fccview/cronmaster",
"website": "https://github.com/fccview/cronmaster",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cr-nmaster.webp",
"config_path": "/opt/cronmaster/.env",
"description": "Self-hosted cron job scheduler with web UI, live logs, auth and prebuilt binaries provided upstream.",
"install_methods": [
{
"type": "default",
"script": "tools/addon/cronmaster.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Credentials are saved to: /root/cronmaster.creds",
"type": "info"
},
{
"text": "Update with: update_cronmaster",
"type": "info"
}
]
}

View File

@@ -9,7 +9,7 @@
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://dawarich.app/docs",
"documentation": "https://dawarich.app/docs/intro",
"website": "https://dawarich.app/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/dawarich.webp",
"config_path": "/opt/dawarich/.env",

View File

@@ -0,0 +1,44 @@
{
"name": "Frigate",
"slug": "frigate",
"categories": [
15
],
"date_created": "2026-02-23",
"type": "ct",
"updateable": false,
"privileged": false,
"config_path": "/config/config.yml",
"interface_port": 5000,
"documentation": "https://docs.frigate.video/",
"website": "https://frigate.video/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/frigate-light.webp",
"description": "Frigate is a complete and local NVR (Network Video Recorder) with realtime AI object detection for CCTV cameras.",
"install_methods": [
{
"type": "default",
"script": "ct/frigate.sh",
"resources": {
"cpu": 4,
"ram": 4096,
"hdd": 20,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "SemanticSearch is not pre-installed due to high resource requirements (8+ cores, 16-24GB RAM, GPU recommended). Manual configuration required if needed.",
"type": "info"
},
{
"text": "OpenVino detector may fail on older CPUs (pre-Haswell/AVX2). If you encounter 'Illegal instruction' errors, consider using alternative detectors.",
"type": "warning"
}
]
}

View File

@@ -1,44 +0,0 @@
{
"name": "Frigate",
"slug": "frigate",
"categories": [
15
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"privileged": true,
"interface_port": 5000,
"documentation": "https://docs.frigate.video/",
"website": "https://frigate.video/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/frigate.webp",
"config_path": "",
"description": "Frigate is an open source NVR built around real-time AI object detection. All processing is performed locally on your own hardware, and your camera feeds never leave your home.",
"install_methods": [
{
"type": "default",
"script": "ct/frigate.sh",
"resources": {
"cpu": 4,
"ram": 4096,
"hdd": 20,
"os": "debian",
"version": "11"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Discussions (explore more advanced methods): `https://github.com/tteck/Proxmox/discussions/2711`",
"type": "info"
},
{
"text": "go2rtc Interface port:`1984`",
"type": "info"
}
]
}

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-02-20T00:19:36Z",
"generated": "2026-02-23T12:14:19Z",
"versions": [
{
"slug": "2fauth",
@@ -88,9 +88,9 @@
{
"slug": "backrest",
"repo": "garethgeorge/backrest",
"version": "v1.11.2",
"version": "v1.12.0",
"pinned": false,
"date": "2026-01-27T06:27:56Z"
"date": "2026-02-22T06:49:49Z"
},
{
"slug": "baikal",
@@ -116,16 +116,16 @@
{
"slug": "bentopdf",
"repo": "alam00000/bentopdf",
"version": "v2.2.1",
"version": "v2.3.1",
"pinned": false,
"date": "2026-02-14T16:33:47Z"
"date": "2026-02-21T09:04:27Z"
},
{
"slug": "beszel",
"repo": "henrygd/beszel",
"version": "v0.18.3",
"version": "v0.18.4",
"pinned": false,
"date": "2026-02-01T19:02:42Z"
"date": "2026-02-20T21:10:52Z"
},
{
"slug": "bichon",
@@ -183,19 +183,26 @@
"pinned": false,
"date": "2025-07-29T16:39:18Z"
},
{
"slug": "calibre-web",
"repo": "janeczku/calibre-web",
"version": "0.6.26",
"pinned": false,
"date": "2026-02-06T21:17:44Z"
},
{
"slug": "checkmate",
"repo": "bluewave-labs/Checkmate",
"version": "v3.3",
"version": "v3.4.0",
"pinned": false,
"date": "2026-01-28T14:25:25Z"
"date": "2026-02-20T21:08:55Z"
},
{
"slug": "cleanuparr",
"repo": "Cleanuparr/Cleanuparr",
"version": "v2.6.3",
"version": "v2.7.1",
"pinned": false,
"date": "2026-02-16T22:41:25Z"
"date": "2026-02-23T09:58:13Z"
},
{
"slug": "cloudreve",
@@ -214,16 +221,16 @@
{
"slug": "commafeed",
"repo": "Athou/commafeed",
"version": "6.2.0",
"version": "7.0.0",
"pinned": false,
"date": "2026-02-09T19:44:58Z"
"date": "2026-02-21T21:54:15Z"
},
{
"slug": "configarr",
"repo": "raydak-labs/configarr",
"version": "v1.21.0",
"version": "v1.22.0",
"pinned": false,
"date": "2026-02-17T22:59:07Z"
"date": "2026-02-20T21:55:46Z"
},
{
"slug": "convertx",
@@ -246,6 +253,13 @@
"pinned": false,
"date": "2026-02-11T17:11:46Z"
},
{
"slug": "cronmaster",
"repo": "fccview/cronmaster",
"version": "2.1.0",
"pinned": false,
"date": "2026-02-11T19:29:11Z"
},
{
"slug": "cryptpad",
"repo": "cryptpad/cryptpad",
@@ -256,9 +270,9 @@
{
"slug": "databasus",
"repo": "databasus/databasus",
"version": "v3.14.1",
"version": "v3.16.2",
"pinned": false,
"date": "2026-02-18T10:43:45Z"
"date": "2026-02-22T21:10:12Z"
},
{
"slug": "dawarich",
@@ -312,9 +326,9 @@
{
"slug": "drawio",
"repo": "jgraph/drawio",
"version": "v29.3.6",
"version": "v29.5.2",
"pinned": false,
"date": "2026-01-28T18:25:02Z"
"date": "2026-02-22T10:36:14Z"
},
{
"slug": "duplicati",
@@ -368,16 +382,16 @@
{
"slug": "firefly",
"repo": "firefly-iii/firefly-iii",
"version": "v6.4.22",
"version": "v6.4.23",
"pinned": false,
"date": "2026-02-15T18:43:08Z"
"date": "2026-02-20T07:02:05Z"
},
{
"slug": "fladder",
"repo": "DonutWare/Fladder",
"version": "v0.9.0",
"version": "v0.10.1",
"pinned": false,
"date": "2026-01-05T17:30:07Z"
"date": "2026-02-21T12:45:53Z"
},
{
"slug": "flaresolverr",
@@ -407,19 +421,26 @@
"pinned": false,
"date": "2026-01-25T18:20:14Z"
},
{
"slug": "frigate",
"repo": "blakeblackshear/frigate",
"version": "v0.16.4",
"pinned": true,
"date": "2026-01-29T00:42:14Z"
},
{
"slug": "gatus",
"repo": "TwiN/gatus",
"version": "v5.34.0",
"version": "v5.35.0",
"pinned": false,
"date": "2026-01-03T03:12:12Z"
"date": "2026-02-20T20:58:03Z"
},
{
"slug": "ghostfolio",
"repo": "ghostfolio/ghostfolio",
"version": "2.240.0",
"version": "2.242.0",
"pinned": false,
"date": "2026-02-18T20:08:56Z"
"date": "2026-02-22T10:01:44Z"
},
{
"slug": "gitea",
@@ -463,6 +484,13 @@
"pinned": false,
"date": "2026-02-13T15:22:31Z"
},
{
"slug": "gramps-web",
"repo": "gramps-project/gramps-web-api",
"version": "v3.7.1.1",
"pinned": false,
"date": "2026-01-30T09:15:46Z"
},
{
"slug": "grist",
"repo": "gristlabs/grist-core",
@@ -522,9 +550,9 @@
{
"slug": "homarr",
"repo": "homarr-labs/homarr",
"version": "v1.53.1",
"version": "v1.53.2",
"pinned": false,
"date": "2026-02-13T19:47:11Z"
"date": "2026-02-20T19:41:55Z"
},
{
"slug": "homebox",
@@ -557,9 +585,9 @@
{
"slug": "huntarr",
"repo": "plexguide/Huntarr.io",
"version": "9.3.7",
"version": "9.4.1",
"pinned": false,
"date": "2026-02-19T01:03:53Z"
"date": "2026-02-23T08:46:37Z"
},
{
"slug": "immich-public-proxy",
@@ -585,16 +613,16 @@
{
"slug": "invoiceninja",
"repo": "invoiceninja/invoiceninja",
"version": "v5.12.64",
"version": "v5.12.65",
"pinned": false,
"date": "2026-02-18T07:59:44Z"
"date": "2026-02-21T01:03:52Z"
},
{
"slug": "jackett",
"repo": "Jackett/Jackett",
"version": "v0.24.1157",
"version": "v0.24.1184",
"pinned": false,
"date": "2026-02-19T05:51:02Z"
"date": "2026-02-23T05:55:36Z"
},
{
"slug": "jellystat",
@@ -641,9 +669,9 @@
{
"slug": "keycloak",
"repo": "keycloak/keycloak",
"version": "26.5.3",
"version": "26.5.4",
"pinned": false,
"date": "2026-02-10T07:30:08Z"
"date": "2026-02-20T09:19:45Z"
},
{
"slug": "kimai",
@@ -704,9 +732,9 @@
{
"slug": "leantime",
"repo": "Leantime/leantime",
"version": "v3.7.0",
"version": "v3.7.1",
"pinned": false,
"date": "2026-02-18T00:02:31Z"
"date": "2026-02-22T01:25:16Z"
},
{
"slug": "librenms",
@@ -725,9 +753,9 @@
{
"slug": "libretranslate",
"repo": "LibreTranslate/LibreTranslate",
"version": "v1.9.0",
"version": "v1.9.3",
"pinned": false,
"date": "2026-02-10T19:05:48Z"
"date": "2026-02-21T19:08:33Z"
},
{
"slug": "lidarr",
@@ -788,9 +816,9 @@
{
"slug": "mail-archiver",
"repo": "s1t5/mail-archiver",
"version": "2602.2",
"version": "2602.3",
"pinned": false,
"date": "2026-02-17T09:46:52Z"
"date": "2026-02-22T20:24:18Z"
},
{
"slug": "managemydamnlife",
@@ -823,9 +851,9 @@
{
"slug": "mediamtx",
"repo": "bluenviron/mediamtx",
"version": "v1.16.1",
"version": "v1.16.2",
"pinned": false,
"date": "2026-02-07T18:58:24Z"
"date": "2026-02-22T17:31:41Z"
},
{
"slug": "meilisearch",
@@ -844,9 +872,9 @@
{
"slug": "metube",
"repo": "alexta69/metube",
"version": "2026.02.19",
"version": "2026.02.22",
"pinned": false,
"date": "2026-02-19T08:24:04Z"
"date": "2026-02-22T00:58:45Z"
},
{
"slug": "miniflux",
@@ -977,9 +1005,9 @@
{
"slug": "ots",
"repo": "Luzifer/ots",
"version": "v1.21.1",
"version": "v1.21.2",
"pinned": false,
"date": "2026-02-16T12:12:23Z"
"date": "2026-02-20T16:20:03Z"
},
{
"slug": "outline",
@@ -1033,16 +1061,16 @@
{
"slug": "paperless-ngx",
"repo": "paperless-ngx/paperless-ngx",
"version": "v2.20.7",
"version": "v2.20.8",
"pinned": false,
"date": "2026-02-16T16:52:23Z"
"date": "2026-02-22T01:40:54Z"
},
{
"slug": "patchmon",
"repo": "PatchMon/PatchMon",
"version": "v1.4.1",
"version": "v1.4.2",
"pinned": false,
"date": "2026-02-16T18:00:13Z"
"date": "2026-02-20T13:15:31Z"
},
{
"slug": "paymenter",
@@ -1110,9 +1138,9 @@
{
"slug": "pocketbase",
"repo": "pocketbase/pocketbase",
"version": "v0.36.4",
"version": "v0.36.5",
"pinned": false,
"date": "2026-02-17T08:02:51Z"
"date": "2026-02-21T11:45:32Z"
},
{
"slug": "pocketid",
@@ -1187,9 +1215,9 @@
{
"slug": "pulse",
"repo": "rcourtman/Pulse",
"version": "v5.1.11",
"version": "v5.1.13",
"pinned": false,
"date": "2026-02-19T20:20:44Z"
"date": "2026-02-22T12:40:41Z"
},
{
"slug": "pve-scripts-local",
@@ -1208,23 +1236,23 @@
{
"slug": "qbittorrent-exporter",
"repo": "martabal/qbittorrent-exporter",
"version": "v1.13.2",
"version": "v1.13.3",
"pinned": false,
"date": "2025-12-13T22:59:03Z"
"date": "2026-02-22T13:01:42Z"
},
{
"slug": "qdrant",
"repo": "qdrant/qdrant",
"version": "v1.16.3",
"version": "v1.17.0",
"pinned": false,
"date": "2025-12-19T17:45:42Z"
"date": "2026-02-20T11:11:50Z"
},
{
"slug": "qui",
"repo": "autobrr/qui",
"version": "v1.13.1",
"version": "v1.14.0",
"pinned": false,
"date": "2026-01-28T20:12:50Z"
"date": "2026-02-21T22:23:46Z"
},
{
"slug": "radarr",
@@ -1250,9 +1278,9 @@
{
"slug": "rdtclient",
"repo": "rogerfar/rdt-client",
"version": "v2.0.121",
"version": "v2.0.123",
"pinned": false,
"date": "2026-02-19T04:48:39Z"
"date": "2026-02-21T23:08:13Z"
},
{
"slug": "reactive-resume",
@@ -1264,9 +1292,9 @@
{
"slug": "recyclarr",
"repo": "recyclarr/recyclarr",
"version": "v7.5.2",
"version": "v8.2.1",
"pinned": false,
"date": "2025-11-30T22:08:46Z"
"date": "2026-02-22T19:19:49Z"
},
{
"slug": "reitti",
@@ -1313,9 +1341,9 @@
{
"slug": "scanopy",
"repo": "scanopy/scanopy",
"version": "v0.14.6",
"version": "v0.14.7",
"pinned": false,
"date": "2026-02-18T16:54:14Z"
"date": "2026-02-23T01:36:44Z"
},
{
"slug": "scraparr",
@@ -1341,9 +1369,9 @@
{
"slug": "semaphore",
"repo": "semaphoreui/semaphore",
"version": "v2.17.8",
"version": "v2.17.12",
"pinned": false,
"date": "2026-02-18T19:46:43Z"
"date": "2026-02-20T09:16:50Z"
},
{
"slug": "shelfmark",
@@ -1355,9 +1383,9 @@
{
"slug": "signoz",
"repo": "SigNoz/signoz-otel-collector",
"version": "v0.142.0",
"version": "v0.142.1",
"pinned": false,
"date": "2026-02-06T11:40:30Z"
"date": "2026-02-21T18:04:07Z"
},
{
"slug": "silverbullet",
@@ -1397,9 +1425,9 @@
{
"slug": "speedtest-tracker",
"repo": "alexjustesen/speedtest-tracker",
"version": "v1.13.9",
"version": "v1.13.10",
"pinned": false,
"date": "2026-02-08T21:48:49Z"
"date": "2026-02-20T03:14:47Z"
},
{
"slug": "spoolman",
@@ -1418,9 +1446,9 @@
{
"slug": "stirling-pdf",
"repo": "Stirling-Tools/Stirling-PDF",
"version": "v2.5.1",
"version": "v2.5.2",
"pinned": false,
"date": "2026-02-18T11:05:34Z"
"date": "2026-02-20T23:20:20Z"
},
{
"slug": "streamlink-webui",
@@ -1436,6 +1464,13 @@
"pinned": false,
"date": "2025-09-19T22:23:28Z"
},
{
"slug": "sure",
"repo": "we-promise/sure",
"version": "chart-v0.6.8-alpha.13",
"pinned": false,
"date": "2026-02-20T11:15:15Z"
},
{
"slug": "tandoor",
"repo": "TandoorRecipes/recipes",
@@ -1502,9 +1537,9 @@
{
"slug": "traccar",
"repo": "traccar/traccar",
"version": "v6.11.1",
"version": "v6.12.1",
"pinned": false,
"date": "2025-12-07T19:19:08Z"
"date": "2026-02-22T18:47:37Z"
},
{
"slug": "tracearr",
@@ -1635,9 +1670,9 @@
{
"slug": "wanderer",
"repo": "meilisearch/meilisearch",
"version": "v1.35.1",
"version": "v1.36.0",
"pinned": false,
"date": "2026-02-16T17:01:17Z"
"date": "2026-02-23T08:13:32Z"
},
{
"slug": "warracker",

View File

@@ -0,0 +1,44 @@
{
"name": "Gramps Web",
"slug": "gramps-web",
"categories": [
12
],
"date_created": "2026-02-22",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 5000,
"documentation": "https://www.grampsweb.org/install_setup/setup/",
"website": "https://www.grampsweb.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/gramps.webp",
"config_path": "/opt/gramps-web/config/config.cfg",
"description": "Gramps Web is a collaborative genealogy platform for browsing, editing and sharing family trees through a modern web interface.",
"install_methods": [
{
"type": "default",
"script": "ct/gramps-web.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 20,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "On first access, create the owner account via the built-in onboarding wizard.",
"type": "info"
},
{
"text": "The initial deployment compiles the frontend and can take several minutes.",
"type": "warning"
}
]
}

View File

@@ -10,7 +10,7 @@
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://maxdorninger.github.io/MediaManager/introduction.html",
"documentation": "https://maxdorninger.github.io/MediaManager/latest/",
"config_path": "/opt/mm/config/config.toml",
"website": "https://github.com/maxdorninger/MediaManager",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/mediamanager.webp",

View File

@@ -0,0 +1,35 @@
{
"name": "SparkyFitness",
"slug": "sparkyfitness",
"categories": [
9
],
"date_created": "2026-02-23",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://codewithcj.github.io/SparkyFitness",
"website": "https://github.com/CodeWithCJ/SparkyFitness",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/sparkyfitness.webp",
"config_path": "/etc/sparkyfitness/.env",
"description": "A self-hosted, privacy-first alternative to MyFitnessPal. Track nutrition, exercise, body metrics, and health data while keeping full control of your data.",
"install_methods": [
{
"type": "default",
"script": "ct/sparkyfitness.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 4,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -0,0 +1,35 @@
{
"name": "Sure",
"slug": "sure",
"categories": [
23
],
"date_created": "2026-02-20",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/we-promise/sure",
"website": "https://sure.am",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/sure-finance.webp",
"config_path": "/etc/sure/.env",
"description": "The personal finance app for everyone. NOT affiliated with or endorsed by Maybe Finance Inc..",
"install_methods": [
{
"type": "default",
"script": "ct/sure.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 6,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -36,7 +36,7 @@ $STD apt install -y \
libavformat-dev
msg_ok "Installed Dependencies"
JAVA_VERSION="11" setup_java
JAVA_VERSION="17" setup_java
setup_mariadb
MARIADB_DB_NAME="guacamole_db" MARIADB_DB_USER="guacamole_user" setup_mariadb_db

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: mikolaj92
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/janeczku/calibre-web
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 \
python3 \
python3-dev \
libldap2-dev \
libsasl2-dev \
libssl-dev \
imagemagick \
libpango-1.0-0 \
libharfbuzz0b \
libpangoft2-1.0-0 \
fonts-liberation
msg_ok "Installed Dependencies"
msg_info "Installing Calibre (for eBook conversion)"
$STD apt install -y calibre
msg_ok "Installed Calibre"
fetch_and_deploy_gh_release "Calibre-Web" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibre-web*.tar.gz"
setup_uv
msg_info "Installing Python Dependencies"
cd /opt/calibre-web
$STD uv venv
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir --upgrade pip setuptools wheel
$STD uv pip install --python /opt/calibre-web/.venv/bin/python --no-cache-dir -r requirements.txt
msg_ok "Installed Python Dependencies"
msg_info "Creating Service"
mkdir -p /opt/calibre-web/data
cat <<EOF >/etc/systemd/system/calibre-web.service
[Unit]
Description=Calibre-Web Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/calibre-web
ExecStart=/opt/calibre-web/.venv/bin/python /opt/calibre-web/cps.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now calibre-web
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Co-Author: remz1337
# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ)
# Co-Authors: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/
@@ -14,60 +14,224 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies (Patience)"
$STD apt-get install -y {git,ca-certificates,automake,build-essential,xz-utils,libtool,ccache,pkg-config,libgtk-3-dev,libavcodec-dev,libavformat-dev,libswscale-dev,libv4l-dev,libxvidcore-dev,libx264-dev,libjpeg-dev,libpng-dev,libtiff-dev,gfortran,openexr,libatlas-base-dev,libssl-dev,libtbb2,libtbb-dev,libdc1394-22-dev,libopenexr-dev,libgstreamer-plugins-base1.0-dev,libgstreamer1.0-dev,gcc,gfortran,libopenblas-dev,liblapack-dev,libusb-1.0-0-dev,jq,moreutils}
source /etc/os-release
if [[ "$VERSION_ID" != "12" ]]; then
msg_error "Frigate requires Debian 12 (Bookworm) due to Python 3.11 dependencies"
exit 1
fi
msg_info "Converting APT sources to DEB822 format"
if [ -f /etc/apt/sources.list ]; then
cat >/etc/apt/sources.list.d/debian.sources <<'EOF'
Types: deb
URIs: http://deb.debian.org/debian
Suites: bookworm
Components: main contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian
Suites: bookworm-updates
Components: main contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://security.debian.org
Suites: bookworm-security
Components: main contrib
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
mv /etc/apt/sources.list /etc/apt/sources.list.bak
$STD apt update
fi
msg_ok "Converted APT sources"
msg_info "Installing Dependencies"
$STD apt install -y \
xz-utils \
python3 \
python3-dev \
python3-pip \
gcc \
pkg-config \
libhdf5-dev \
build-essential \
automake \
libtool \
ccache \
libusb-1.0-0-dev \
apt-transport-https \
cmake \
git \
libgtk-3-dev \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libv4l-dev \
libxvidcore-dev \
libx264-dev \
libjpeg-dev \
libpng-dev \
libtiff-dev \
gfortran \
openexr \
libssl-dev \
libtbbmalloc2 \
libtbb-dev \
libdc1394-dev \
libopenexr-dev \
libgstreamer-plugins-base1.0-dev \
libgstreamer1.0-dev \
tclsh \
libopenblas-dev \
liblapack-dev \
make \
moreutils
msg_ok "Installed Dependencies"
msg_info "Setup Python3"
$STD apt-get install -y {python3,python3-dev,python3-setuptools,python3-distutils,python3-pip}
$STD pip install --upgrade pip
msg_ok "Setup Python3"
NODE_VERSION="22" setup_nodejs
msg_info "Installing go2rtc"
mkdir -p /usr/local/go2rtc/bin
cd /usr/local/go2rtc/bin
curl -fsSL "https://github.com/AlexxIT/go2rtc/releases/latest/download/go2rtc_linux_amd64" -o "go2rtc"
chmod +x go2rtc
$STD ln -svf /usr/local/go2rtc/bin/go2rtc /usr/local/bin/go2rtc
msg_ok "Installed go2rtc"
setup_hwaccel
msg_info "Installing Frigate v0.14.1 (Perseverance)"
cd ~
mkdir -p /opt/frigate/models
curl -fsSL "https://github.com/blakeblackshear/frigate/archive/refs/tags/v0.14.1.tar.gz" -o "frigate.tar.gz"
tar -xzf frigate.tar.gz -C /opt/frigate --strip-components 1
rm -rf frigate.tar.gz
cd /opt/frigate
$STD pip3 wheel --wheel-dir=/wheels -r /opt/frigate/docker/main/requirements-wheels.txt
cp -a /opt/frigate/docker/main/rootfs/. /
export TARGETARCH="amd64"
echo 'libc6 libraries/restart-without-asking boolean true' | debconf-set-selections
$STD /opt/frigate/docker/main/install_deps.sh
$STD apt update
$STD ln -svf /usr/lib/btbn-ffmpeg/bin/ffmpeg /usr/local/bin/ffmpeg
$STD ln -svf /usr/lib/btbn-ffmpeg/bin/ffprobe /usr/local/bin/ffprobe
export CCACHE_DIR=/root/.ccache
export CCACHE_MAXSIZE=2G
export APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
export PIP_BREAK_SYSTEM_PACKAGES=1
export NVIDIA_VISIBLE_DEVICES=all
export NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
export TOKENIZERS_PARALLELISM=true
export TRANSFORMERS_NO_ADVISORY_WARNINGS=1
export OPENCV_FFMPEG_LOGLEVEL=8
export HAILORT_LOGGER_PATH=NONE
fetch_and_deploy_gh_release "frigate" "blakeblackshear/frigate" "tarball" "v0.16.4" "/opt/frigate"
msg_info "Building Nginx"
$STD bash /opt/frigate/docker/main/build_nginx.sh
sed -e '/s6-notifyoncheck/ s/^#*/#/' -i /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
ln -sf /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
msg_ok "Built Nginx"
msg_info "Building SQLite Extensions"
$STD bash /opt/frigate/docker/main/build_sqlite_vec.sh
msg_ok "Built SQLite Extensions"
fetch_and_deploy_gh_release "go2rtc" "AlexxIT/go2rtc" "singlefile" "latest" "/usr/local/go2rtc/bin" "go2rtc_linux_amd64"
msg_info "Installing Tempio"
sed -i 's|/rootfs/usr/local|/usr/local|g' /opt/frigate/docker/main/install_tempio.sh
$STD bash /opt/frigate/docker/main/install_tempio.sh
ln -sf /usr/local/tempio/bin/tempio /usr/local/bin/tempio
msg_ok "Installed Tempio"
msg_info "Building libUSB"
fetch_and_deploy_gh_release "libusb" "libusb/libusb" "tarball" "v1.0.26" "/opt/libusb"
cd /opt/libusb
$STD ./bootstrap.sh
$STD ./configure CC='ccache gcc' CCX='ccache g++' --disable-udev --enable-shared
$STD make -j "$(nproc)"
cd /opt/libusb/libusb
mkdir -p /usr/local/lib /usr/local/include/libusb-1.0 /usr/local/lib/pkgconfig
$STD bash ../libtool --mode=install /usr/bin/install -c libusb-1.0.la /usr/local/lib
install -c -m 644 libusb.h /usr/local/include/libusb-1.0
cd /opt/libusb/
install -c -m 644 libusb-1.0.pc /usr/local/lib/pkgconfig
ldconfig
msg_ok "Built libUSB"
msg_info "Installing Python Dependencies"
$STD pip3 install -r /opt/frigate/docker/main/requirements.txt
msg_ok "Installed Python Dependencies"
msg_info "Building Python Wheels (Patience)"
mkdir -p /wheels
sed -i 's|^SQLITE3_VERSION=.*|SQLITE3_VERSION="version-3.46.0"|g' /opt/frigate/docker/main/build_pysqlite3.sh
$STD bash /opt/frigate/docker/main/build_pysqlite3.sh
for i in {1..3}; do
$STD pip3 wheel --wheel-dir=/wheels -r /opt/frigate/docker/main/requirements-wheels.txt --default-timeout=300 --retries=3 && break
[[ $i -lt 3 ]] && sleep 10
done
msg_ok "Built Python Wheels"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
msg_info "Downloading Inference Models"
mkdir -p /models /openvino-model
wget -q -O /edgetpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite
wget -q -O /models/cpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite
cp /opt/frigate/labelmap.txt /labelmap.txt
msg_ok "Downloaded Inference Models"
msg_info "Downloading Audio Model"
wget -q -O /tmp/yamnet.tar.gz https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download
$STD tar xzf /tmp/yamnet.tar.gz -C /
mv /1.tflite /cpu_audio_model.tflite
cp /opt/frigate/audio-labelmap.txt /audio-labelmap.txt
rm -f /tmp/yamnet.tar.gz
msg_ok "Downloaded Audio Model"
msg_info "Installing HailoRT Runtime"
$STD bash /opt/frigate/docker/main/install_hailort.sh
cp -a /opt/frigate/docker/main/rootfs/. /
sed -i '/^.*unset DEBIAN_FRONTEND.*$/d' /opt/frigate/docker/main/install_deps.sh
echo "libedgetpu1-max libedgetpu/accepted-eula boolean true" | debconf-set-selections
echo "libedgetpu1-max libedgetpu/install-confirm-max boolean true" | debconf-set-selections
# Allow Frigate's Intel media packages to overwrite files from system GPU driver packages
echo 'force-overwrite' >/etc/dpkg/dpkg.cfg.d/force-overwrite
$STD bash /opt/frigate/docker/main/install_deps.sh
rm -f /etc/dpkg/dpkg.cfg.d/force-overwrite
$STD pip3 install -U /wheels/*.whl
ldconfig
msg_ok "Installed HailoRT Runtime"
msg_info "Installing OpenVino"
$STD pip3 install -r /opt/frigate/docker/main/requirements-ov.txt
msg_ok "Installed OpenVino"
msg_info "Building OpenVino Model"
cd /models
wget -q http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz
$STD tar -zxf ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz --no-same-owner
if $STD python3 /opt/frigate/docker/main/build_ov_model.py; then
cp /models/ssdlite_mobilenet_v2.xml /openvino-model/
cp /models/ssdlite_mobilenet_v2.bin /openvino-model/
wget -q https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt -O /openvino-model/coco_91cl_bkgr.txt
sed -i 's/truck/car/g' /openvino-model/coco_91cl_bkgr.txt
msg_ok "Built OpenVino Model"
else
msg_warn "OpenVino build failed (CPU may not support required instructions). Frigate will use CPU model."
fi
msg_info "Building Frigate Application (Patience)"
cd /opt/frigate
$STD pip3 install -r /opt/frigate/docker/main/requirements-dev.txt
$STD /opt/frigate/.devcontainer/initialize.sh
$STD bash /opt/frigate/.devcontainer/initialize.sh
$STD make version
cd /opt/frigate/web
$STD npm install
$STD npm run build
cp -r /opt/frigate/web/dist/* /opt/frigate/web/
cp -r /opt/frigate/config/. /config
sed -i '/^s6-svc -O \.$/s/^/#/' /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
msg_ok "Built Frigate Application"
msg_info "Configuring Frigate"
mkdir -p /config /media/frigate
cp -r /opt/frigate/config/. /config
curl -fsSL "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4" -o "/media/frigate/person-bicycle-car-detection.mp4"
echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab
cat <<EOF >/etc/frigate.env
DEFAULT_FFMPEG_VERSION="7.0"
INCLUDED_FFMPEG_VERSIONS="7.0:5.0"
EOF
cat <<EOF >/config/config.yml
mqtt:
enabled: false
cameras:
test:
ffmpeg:
#hwaccel_args: preset-vaapi
inputs:
- path: /media/frigate/person-bicycle-car-detection.mp4
input_args: -re -stream_loop -1 -fflags +genpts
@@ -78,96 +242,42 @@ cameras:
height: 1080
width: 1920
fps: 5
auth:
enabled: false
detect:
enabled: false
EOF
ln -sf /config/config.yml /opt/frigate/config/config.yml
if [[ "$CTTYPE" == "0" ]]; then
sed -i -e 's/^kvm:x:104:$/render:x:104:root,frigate/' -e 's/^render:x:105:root$/kvm:x:105:/' /etc/group
else
sed -i -e 's/^kvm:x:104:$/render:x:104:frigate/' -e 's/^render:x:105:$/kvm:x:105:/' /etc/group
fi
echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab
msg_ok "Installed Frigate"
if grep -q -o -m1 -E 'avx[^ ]*' /proc/cpuinfo; then
msg_ok "AVX Support Detected"
msg_info "Installing Openvino Object Detection Model (Resilience)"
$STD pip install -r /opt/frigate/docker/main/requirements-ov.txt
cd /opt/frigate/models
export ENABLE_ANALYTICS=NO
$STD /usr/local/bin/omz_downloader --name ssdlite_mobilenet_v2 --num_attempts 2
$STD /usr/local/bin/omz_converter --name ssdlite_mobilenet_v2 --precision FP16 --mo /usr/local/bin/mo
cd /
cp -r /opt/frigate/models/public/ssdlite_mobilenet_v2 openvino-model
curl -fsSL "https://github.com/openvinotoolkit/open_model_zoo/raw/master/data/dataset_classes/coco_91cl_bkgr.txt" -o "openvino-model/coco_91cl_bkgr.txt"
sed -i 's/truck/car/g' openvino-model/coco_91cl_bkgr.txt
if grep -q -o -m1 -E 'avx[^ ]*|sse4_2' /proc/cpuinfo; then
cat <<EOF >>/config/config.yml
ffmpeg:
hwaccel_args: auto
detectors:
ov:
detector01:
type: openvino
device: CPU
model:
path: /openvino-model/FP16/ssdlite_mobilenet_v2.xml
model:
width: 300
height: 300
input_tensor: nhwc
input_pixel_format: bgr
path: /openvino-model/ssdlite_mobilenet_v2.xml
labelmap_path: /openvino-model/coco_91cl_bkgr.txt
EOF
msg_ok "Installed Openvino Object Detection Model"
else
cat <<EOF >>/config/config.yml
ffmpeg:
hwaccel_args: auto
model:
path: /cpu_model.tflite
EOF
fi
msg_info "Installing Coral Object Detection Model (Patience)"
cd /opt/frigate
export CCACHE_DIR=/root/.ccache
export CCACHE_MAXSIZE=2G
curl -fsSL "https://github.com/libusb/libusb/archive/v1.0.26.zip" -o "v1.0.26.zip"
$STD unzip v1.0.26.zip
rm v1.0.26.zip
cd libusb-1.0.26
$STD ./bootstrap.sh
$STD ./configure --disable-udev --enable-shared
$STD make -j $(nproc --all)
cd /opt/frigate/libusb-1.0.26/libusb
mkdir -p /usr/local/lib
$STD /bin/bash ../libtool --mode=install /usr/bin/install -c libusb-1.0.la '/usr/local/lib'
mkdir -p /usr/local/include/libusb-1.0
$STD /usr/bin/install -c -m 644 libusb.h '/usr/local/include/libusb-1.0'
ldconfig
cd /
curl -fsSL "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite" -o "edgetpu_model.tflite"
curl -fsSL "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite" -o "cpu_model.tflite"
cp /opt/frigate/labelmap.txt /labelmap.txt
curl -fsSL "https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download" -o "yamnet-tflite-classification-tflite-v1.tar.gz"
tar xzf yamnet-tflite-classification-tflite-v1.tar.gz
rm -rf yamnet-tflite-classification-tflite-v1.tar.gz
mv 1.tflite cpu_audio_model.tflite
cp /opt/frigate/audio-labelmap.txt /audio-labelmap.txt
mkdir -p /media/frigate
curl -fsSL "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4" -o "/media/frigate/person-bicycle-car-detection.mp4"
msg_ok "Installed Coral Object Detection Model"
msg_info "Building Nginx with Custom Modules"
$STD /opt/frigate/docker/main/build_nginx.sh
sed -e '/s6-notifyoncheck/ s/^#*/#/' -i /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
ln -sf /usr/local/nginx/sbin/nginx /usr/local/bin/nginx
msg_ok "Built Nginx"
msg_info "Installing Tempio"
sed -i 's|/rootfs/usr/local|/usr/local|g' /opt/frigate/docker/main/install_tempio.sh
$STD /opt/frigate/docker/main/install_tempio.sh
ln -sf /usr/local/tempio/bin/tempio /usr/local/bin/tempio
msg_ok "Installed Tempio"
msg_ok "Configured Frigate"
msg_info "Creating Services"
cat <<EOF >/etc/systemd/system/create_directories.service
[Unit]
Description=Create necessary directories for logs
Description=Create necessary directories for Frigate logs
Before=frigate.service go2rtc.service nginx.service
[Service]
Type=oneshot
@@ -176,13 +286,11 @@ ExecStart=/bin/bash -c '/bin/mkdir -p /dev/shm/logs/{frigate,go2rtc,nginx} && /b
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now create_directories
sleep 3
cat <<EOF >/etc/systemd/system/go2rtc.service
[Unit]
Description=go2rtc service
After=network.target
After=create_directories.service
Description=go2rtc streaming service
After=network.target create_directories.service
StartLimitIntervalSec=0
[Service]
@@ -190,7 +298,8 @@ Type=simple
Restart=always
RestartSec=1
User=root
ExecStartPre=+rm /dev/shm/logs/go2rtc/current
EnvironmentFile=/etc/frigate.env
ExecStartPre=+rm -f /dev/shm/logs/go2rtc/current
ExecStart=/bin/bash -c "bash /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/run 2> >(/usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S ' >&2) | /usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S '"
StandardOutput=file:/dev/shm/logs/go2rtc/current
StandardError=file:/dev/shm/logs/go2rtc/current
@@ -198,13 +307,11 @@ StandardError=file:/dev/shm/logs/go2rtc/current
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now go2rtc
sleep 3
cat <<EOF >/etc/systemd/system/frigate.service
[Unit]
Description=Frigate service
After=go2rtc.service
After=create_directories.service
Description=Frigate NVR service
After=go2rtc.service create_directories.service
StartLimitIntervalSec=0
[Service]
@@ -212,8 +319,8 @@ Type=simple
Restart=always
RestartSec=1
User=root
# Environment=PLUS_API_KEY=
ExecStartPre=+rm /dev/shm/logs/frigate/current
EnvironmentFile=/etc/frigate.env
ExecStartPre=+rm -f /dev/shm/logs/frigate/current
ExecStart=/bin/bash -c "bash /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run 2> >(/usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S ' >&2) | /usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S '"
StandardOutput=file:/dev/shm/logs/frigate/current
StandardError=file:/dev/shm/logs/frigate/current
@@ -221,13 +328,11 @@ StandardError=file:/dev/shm/logs/frigate/current
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now frigate
sleep 3
cat <<EOF >/etc/systemd/system/nginx.service
[Unit]
Description=Nginx service
After=frigate.service
After=create_directories.service
Description=Nginx reverse proxy for Frigate
After=frigate.service create_directories.service
StartLimitIntervalSec=0
[Service]
@@ -235,7 +340,7 @@ Type=simple
Restart=always
RestartSec=1
User=root
ExecStartPre=+rm /dev/shm/logs/nginx/current
ExecStartPre=+rm -f /dev/shm/logs/nginx/current
ExecStart=/bin/bash -c "bash /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run 2> >(/usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S ' >&2) | /usr/bin/ts '%%Y-%%m-%%d %%H:%%M:%%.S '"
StandardOutput=file:/dev/shm/logs/nginx/current
StandardError=file:/dev/shm/logs/nginx/current
@@ -243,8 +348,20 @@ StandardError=file:/dev/shm/logs/nginx/current
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable -q --now create_directories
sleep 2
systemctl enable -q --now go2rtc
sleep 2
systemctl enable -q --now frigate
sleep 2
systemctl enable -q --now nginx
msg_ok "Configured Services"
msg_ok "Created Services"
msg_info "Cleaning Up"
rm -rf /opt/libusb /wheels /models/*.tar.gz
msg_ok "Cleaned Up"
motd_ssh
customize

View File

@@ -0,0 +1,118 @@
#!/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://www.grampsweb.org/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
appstream \
build-essential \
ffmpeg \
gettext \
gobject-introspection \
gir1.2-gexiv2-0.10 \
gir1.2-gtk-3.0 \
gir1.2-osmgpsmap-1.0 \
gir1.2-pango-1.0 \
git \
graphviz \
libcairo2-dev \
libgirepository1.0-dev \
libglib2.0-dev \
libicu-dev \
libopencv-dev \
pkg-config \
poppler-utils \
python3-dev \
tesseract-ocr
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv
NODE_VERSION="22" setup_nodejs
fetch_and_deploy_gh_release "gramps-web-api" "gramps-project/gramps-web-api" "tarball" "latest" "/opt/gramps-web-api"
fetch_and_deploy_gh_release "gramps-web" "gramps-project/gramps-web" "tarball" "latest" "/opt/gramps-web/frontend"
msg_info "Setting up Gramps Web"
mkdir -p \
/opt/gramps-web/config \
/opt/gramps-web/data/cache/export \
/opt/gramps-web/data/cache/persistent \
/opt/gramps-web/data/cache/report \
/opt/gramps-web/data/cache/request \
/opt/gramps-web/data/cache/thumbnail \
/opt/gramps-web/data/gramps/grampsdb \
/opt/gramps-web/data/indexdir \
/opt/gramps-web/data/media \
/opt/gramps-web/data/users
SECRET_KEY="$(openssl rand -hex 32)"
cat <<EOF >/opt/gramps-web/config/config.cfg
TREE="Gramps Web"
SECRET_KEY="${SECRET_KEY}"
BASE_URL="http://${LOCAL_IP}:5000"
USER_DB_URI="sqlite:////opt/gramps-web/data/users/users.sqlite"
SEARCH_INDEX_DB_URI="sqlite:////opt/gramps-web/data/indexdir/search_index.db"
MEDIA_BASE_DIR="/opt/gramps-web/data/media"
STATIC_PATH="/opt/gramps-web/frontend/dist"
THUMBNAIL_CACHE_CONFIG={"CACHE_TYPE":"FileSystemCache","CACHE_DIR":"/opt/gramps-web/data/cache/thumbnail","CACHE_THRESHOLD":1000,"CACHE_DEFAULT_TIMEOUT":0}
REQUEST_CACHE_CONFIG={"CACHE_TYPE":"FileSystemCache","CACHE_DIR":"/opt/gramps-web/data/cache/request","CACHE_THRESHOLD":1000,"CACHE_DEFAULT_TIMEOUT":0}
PERSISTENT_CACHE_CONFIG={"CACHE_TYPE":"FileSystemCache","CACHE_DIR":"/opt/gramps-web/data/cache/persistent","CACHE_THRESHOLD":0,"CACHE_DEFAULT_TIMEOUT":0}
REPORT_DIR="/opt/gramps-web/data/cache/report"
EXPORT_DIR="/opt/gramps-web/data/cache/export"
EOF
$STD uv venv -c -p python3.12 /opt/gramps-web/venv
source /opt/gramps-web/venv/bin/activate
$STD uv pip install --no-cache-dir --upgrade pip setuptools wheel
$STD uv pip install --no-cache-dir gunicorn
$STD uv pip install --no-cache-dir /opt/gramps-web-api
cd /opt/gramps-web/frontend
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
$STD corepack enable
$STD npm install
$STD npm run build
cd /opt/gramps-web-api
GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg \
ALEMBIC_CONFIG=/opt/gramps-web-api/alembic.ini \
GRAMPSHOME=/opt/gramps-web/data/gramps \
GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb \
$STD /opt/gramps-web/venv/bin/python3 -m gramps_webapi user migrate
msg_ok "Set up Gramps Web"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/gramps-web.service
[Unit]
Description=Gramps Web Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/gramps-web-api
Environment=GRAMPS_API_CONFIG=/opt/gramps-web/config/config.cfg
Environment=GRAMPSHOME=/opt/gramps-web/data/gramps
Environment=GRAMPS_DATABASE_PATH=/opt/gramps-web/data/gramps/grampsdb
Environment=PATH=/opt/gramps-web/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ExecStart=/opt/gramps-web/venv/bin/gunicorn -w 2 -b 0.0.0.0:5000 gramps_webapi.wsgi:app --timeout 120 --limit-request-line 8190
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now gramps-web
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -1,41 +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
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

@@ -30,7 +30,7 @@ setup_meilisearch
fetch_and_deploy_gh_release "karakeep" "karakeep-app/karakeep" "tarball"
cd /opt/karakeep
MODULE_VERSION="$(jq -r '.packageManager | split("@")[1]' /opt/karakeep/package.json)"
NODE_VERSION="22" NODE_MODULE="pnpm@${MODULE_VERSION}" setup_nodejs
NODE_VERSION="24" NODE_MODULE="pnpm@${MODULE_VERSION}" setup_nodejs
msg_info "Installing karakeep"
export PUPPETEER_SKIP_DOWNLOAD="true"

View File

@@ -50,6 +50,7 @@ cp .env.sample .env
sed -i "s#http://localhost:1337#http://$LOCAL_IP:1337#g" /opt/planka/.env
sed -i "s#postgres@localhost#planka:$DB_PASS@localhost#g" /opt/planka/.env
sed -i "s#notsecretkey#$SECRET_KEY#g" /opt/planka/.env
mkdir -p /opt/planka/data/protected/{favicons,user-avatars,background-images} /opt/planka/data/private/attachments
$STD npm run db:init
msg_ok "Configured PLANKA"

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.plex.tv/
@@ -16,19 +16,16 @@ update_os
setup_hwaccel
msg_info "Setting Up Plex Media Server Repository"
curl -fsSL https://downloads.plex.tv/plex-keys/PlexSign.key | tee /usr/share/keyrings/PlexSign.asc >/dev/null
cat <<EOF >/etc/apt/sources.list.d/plexmediaserver.sources
Types: deb
URIs: https://downloads.plex.tv/repo/deb/
Suites: public
Components: main
Signed-By: /usr/share/keyrings/PlexSign.asc
EOF
setup_deb822_repo \
"plexmediaserver" \
"https://downloads.plex.tv/plex-keys/PlexSign.v2.key" \
"https://repo.plex.tv/deb/" \
"public" \
"main"
msg_ok "Set Up Plex Media Server Repository"
msg_info "Installing Plex Media Server"
$STD apt update
$STD apt -o Dpkg::Options::="--force-confold" install -y plexmediaserver
$STD apt install -y plexmediaserver
if [[ "$CTTYPE" == "0" ]]; then
sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:root,plex/' -e 's/^render:x:108:root$/ssl-cert:x:108:plex/' /etc/group
else

View File

@@ -20,7 +20,7 @@ msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "recyclarr" "recyclarr/recyclarr" "prebuild" "latest" "/usr/local/bin" "recyclarr-linux-x64.tar.xz"
msg_info "Configuring Recyclarr"
mkdir -p /root/.config/recyclarr
mkdir -p /root/.config/recyclarr/{configs,includes}
$STD recyclarr config create
msg_ok "Configured Recyclarr"

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Tom Frenzel (tomfrenzel)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/CodeWithCJ/SparkyFitness
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
msg_ok "Installed Dependencies"
NODE_VERSION="25" setup_nodejs
PG_VERSION="18" setup_postgresql
PG_DB_NAME="sparkyfitness" PG_DB_USER="sparky" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
fetch_and_deploy_gh_release sparkyfitness "CodeWithCJ/SparkyFitness" "tarball" "latest"
msg_info "Configuring Sparky Fitness"
mkdir -p "/etc/sparkyfitness" "/var/lib/sparkyfitness/uploads" "/var/lib/sparkyfitness/backup" "/var/www/sparkyfitness"
cp "/opt/sparkyfitness/docker/.env.example" "/etc/sparkyfitness/.env"
sed \
-i \
-e "s|^#\?SPARKY_FITNESS_DB_HOST=.*|SPARKY_FITNESS_DB_HOST=localhost|" \
-e "s|^#\?SPARKY_FITNESS_DB_PORT=.*|SPARKY_FITNESS_DB_PORT=5432|" \
-e "s|^SPARKY_FITNESS_DB_NAME=.*|SPARKY_FITNESS_DB_NAME=sparkyfitness|" \
-e "s|^SPARKY_FITNESS_DB_USER=.*|SPARKY_FITNESS_DB_USER=sparky|" \
-e "s|^SPARKY_FITNESS_DB_PASSWORD=.*|SPARKY_FITNESS_DB_PASSWORD=${PG_DB_PASS}|" \
-e "s|^SPARKY_FITNESS_APP_DB_USER=.*|SPARKY_FITNESS_APP_DB_USER=sparky_app|" \
-e "s|^SPARKY_FITNESS_APP_DB_PASSWORD=.*|SPARKY_FITNESS_APP_DB_PASSWORD=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c20)|" \
-e "s|^SPARKY_FITNESS_SERVER_HOST=.*|SPARKY_FITNESS_SERVER_HOST=localhost|" \
-e "s|^SPARKY_FITNESS_SERVER_PORT=.*|SPARKY_FITNESS_SERVER_PORT=3010|" \
-e "s|^SPARKY_FITNESS_FRONTEND_URL=.*|SPARKY_FITNESS_FRONTEND_URL=http://${LOCAL_IP}:80|" \
-e "s|^SPARKY_FITNESS_API_ENCRYPTION_KEY=.*|SPARKY_FITNESS_API_ENCRYPTION_KEY=$(openssl rand -hex 32)|" \
-e "s|^BETTER_AUTH_SECRET=.*|BETTER_AUTH_SECRET=$(openssl rand -hex 32)|" \
"/etc/sparkyfitness/.env"
msg_ok "Configured Sparky Fitness"
msg_info "Building Backend"
cd /opt/sparkyfitness/SparkyFitnessServer
$STD npm install
msg_ok "Built Backend"
msg_info "Building Frontend (Patience)"
cd /opt/sparkyfitness/SparkyFitnessFrontend
$STD npm install
$STD npm run build
cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/
msg_ok "Built Frontend"
msg_info "Creating SparkyFitness Service"
cat <<EOF >/etc/systemd/system/sparkyfitness-server.service
[Unit]
Description=SparkyFitness Backend Service
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
WorkingDirectory=/opt/sparkyfitness/SparkyFitnessServer
EnvironmentFile=/etc/sparkyfitness/.env
ExecStart=/usr/bin/node SparkyFitnessServer.js
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now sparkyfitness-server
msg_ok "Created SparkyFitness Service"
msg_info "Configuring Nginx"
sed \
-e 's|${SPARKY_FITNESS_SERVER_HOST}|127.0.0.1|g' \
-e 's|${SPARKY_FITNESS_SERVER_PORT}|3010|g' \
-e 's|root /usr/share/nginx/html;|root /var/www/sparkyfitness;|g' \
-e 's|server_name localhost;|server_name _;|g' \
"/opt/sparkyfitness/docker/nginx.conf" >/etc/nginx/sites-available/sparkyfitness
ln -sf /etc/nginx/sites-available/sparkyfitness /etc/nginx/sites-enabled/sparkyfitness
rm -f /etc/nginx/sites-enabled/default
$STD nginx -t
$STD systemctl enable -q --now nginx
$STD systemctl reload nginx
msg_ok "Configured Nginx"
motd_ssh
customize
cleanup_lxc

110
install/sure-install.sh Normal file
View File

@@ -0,0 +1,110 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: vhsdream
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://sure.am
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 \
redis-server \
pkg-config \
libpq-dev \
libvips
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "Sure" "we-promise/sure" "tarball" "latest" "/opt/sure"
PG_VERSION="$(sed -n '/postgres:/s/[^[:digit:]]*//p' /opt/sure/compose.example.yml)" setup_postgresql
PG_DB_NAME=sure_production PG_DB_USER=sure_user setup_postgresql_db
RUBY_VERSION="$(cat /opt/sure/.ruby-version)" RUBY_INSTALL_RAILS=false setup_ruby
msg_info "Building Sure"
cd /opt/sure
export RAILS_ENV=production
export BUNDLE_DEPLOYMENT=1
export BUNDLE_WITHOUT=development
$STD ./bin/bundle install
$STD ./bin/bundle exec bootsnap precompile --gemfile -j 0
$STD ./bin/bundle exec bootsnap precompile -j 0 app/ lib/
export SECRET_KEY_BASE_DUMMY=1 && $STD ./bin/rails assets:precompile
unset SECRET_KEY_BASE_DUMMY
msg_ok "Built Sure"
msg_info "Configuring Sure"
KEY="$(openssl rand -hex 64)"
mkdir -p /etc/sure
mv /opt/sure/.env.example /etc/sure/.env
sed -i -e "/^SECRET_KEY_BASE=/s/secret-value/${KEY}/" \
-e 's/_KEY_BASE=.*$/&\n\nRAILS_FORCE_SSL=false \
\
# Change to true when using a reverse proxy \
RAILS_ASSUME_SSL=false/' \
-e "/POSTGRES_PASSWORD=/s/postgres/${PG_DB_PASS}/" \
-e "/POSTGRES_USER=/s/postgres/${PG_DB_USER}\\
POSTGRES_DB=${PG_DB_NAME}/" \
-e "s|^APP_DOMAIN=|&${LOCAL_IP}|" /etc/sure/.env
msg_ok "Configured Sure"
msg_info "Creating Services"
cat <<EOF >/etc/systemd/system/sure.service
[Unit]
Description=Sure Service
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/sure
Environment=RAILS_ENV=production
Environment=BUNDLE_DEPLOYMENT=1
Environment=BUNDLE_WITHOUT=development
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/bin:\$PATH
EnvironmentFile=/etc/sure/.env
ExecStartPre=/opt/sure/bin/rails db:prepare
ExecStart=/opt/sure/bin/rails server
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
cat <<EOF >/etc/systemd/system/sure-worker.service
[Unit]
Description=Sure Background Worker (Sidekiq)
After=network.target redis-server.service
[Service]
Type=simple
WorkingDirectory=/opt/sure
Environment=RAILS_ENV=production
Environment=BUNDLE_DEPLOYMENT=1
Environment=BUNDLE_WITHOUT=development
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/bin:/usr/local/bin:/sbin:/bin
EnvironmentFile=/etc/sure/.env
ExecStart=/opt/sure/bin/bundle exec sidekiq -e production
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
$STD systemctl enable -q --now sure sure-worker
msg_ok "Created Services"
motd_ssh
customize
cleanup_lxc

View File

@@ -28,9 +28,10 @@ setup_deb822_repo \
"stable" \
"main"
$STD apt install -y elasticsearch
echo "-Xms2g" >>/etc/elasticsearch/jvm.options
echo "-Xmx2g" >>/etc/elasticsearch/jvm.options
sed -i 's/^-Xms.*/-Xms2g/' /etc/elasticsearch/jvm.options
sed -i 's/^-Xmx.*/-Xmx2g/' /etc/elasticsearch/jvm.options
$STD /usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-attachment -b
systemctl daemon-reload
systemctl enable -q elasticsearch
systemctl restart -q elasticsearch
msg_ok "Setup Elasticsearch"

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
@@ -350,6 +354,55 @@ get_error_text() {
fi
}
# ------------------------------------------------------------------------------
# get_full_log()
#
# - Returns the FULL installation log (build + install combined)
# - Calls ensure_log_on_host() to pull container log if needed
# - Strips ANSI escape codes and carriage returns
# - Truncates to max_bytes (default: 120KB) to stay within API limits
# - Used for the error telemetry field (full trace instead of 20 lines)
# ------------------------------------------------------------------------------
get_full_log() {
local max_bytes="${1:-122880}" # 120KB default
local logfile=""
# Ensure logs are available on host (pulls from container if needed)
if declare -f ensure_log_on_host >/dev/null 2>&1; then
ensure_log_on_host
fi
# Try combined log first (most complete)
if [[ -n "${CTID:-}" && -n "${SESSION_ID:-}" ]]; then
local combined_log="/tmp/${NSAPP:-lxc}-${CTID}-${SESSION_ID}.log"
if [[ -s "$combined_log" ]]; then
logfile="$combined_log"
fi
fi
# Fall back to INSTALL_LOG
if [[ -z "$logfile" || ! -s "$logfile" ]]; then
if [[ -n "${INSTALL_LOG:-}" && -s "${INSTALL_LOG}" ]]; then
logfile="$INSTALL_LOG"
fi
fi
# Fall back to BUILD_LOG
if [[ -z "$logfile" || ! -s "$logfile" ]]; then
if [[ -n "${BUILD_LOG:-}" && -s "${BUILD_LOG}" ]]; then
logfile="$BUILD_LOG"
fi
fi
if [[ -n "$logfile" && -s "$logfile" ]]; then
# Strip ANSI codes, carriage returns, and anonymize IP addresses (GDPR)
sed 's/\r$//' "$logfile" 2>/dev/null |
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g' |
sed -E 's/([0-9]{1,3}\.)[0-9]{1,3}\.[0-9]{1,3}/\1x.x/g' |
head -c "$max_bytes"
fi
}
# ------------------------------------------------------------------------------
# build_error_string()
#
@@ -692,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
@@ -703,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
}
# ------------------------------------------------------------------------------
@@ -782,11 +839,15 @@ post_update_to_api() {
else
exit_code=1
fi
# Get log lines and build structured error string
local error_text=""
error_text=$(get_error_text)
# Get full installation log for error field
local log_text=""
log_text=$(get_full_log 122880) || true # 120KB max
if [[ -z "$log_text" ]]; then
# Fallback to last 20 lines
log_text=$(get_error_text)
fi
local full_error
full_error=$(build_error_string "$exit_code" "$error_text")
full_error=$(build_error_string "$exit_code" "$log_text")
error=$(json_escape "$full_error")
short_error=$(json_escape "$(explain_exit_code "$exit_code")")
error_category=$(categorize_error "$exit_code")
@@ -807,7 +868,7 @@ post_update_to_api() {
local http_code=""
# ── Attempt 1: Full payload with complete error text ──
# ── Attempt 1: Full payload with complete error text (includes full log) ──
local JSON_PAYLOAD
JSON_PAYLOAD=$(
cat <<EOF
@@ -840,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"
@@ -883,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"
@@ -911,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.
}
# ==============================================================================
@@ -969,16 +1036,16 @@ categorize_error() {
# Python environment errors
# (already covered: 160-162 under dependency)
# Aborted by user
130) echo "aborted" ;;
# Aborted by user (SIGHUP=terminal closed, SIGINT=Ctrl+C, SIGTERM=killed)
129 | 130 | 143) echo "user_aborted" ;;
# Resource errors (OOM, SIGKILL, SIGABRT)
134 | 137) echo "resource" ;;
# Signal/Process errors (SIGTERM, SIGPIPE, SIGSEGV)
139 | 141 | 143) echo "signal" ;;
# Signal/Process errors (SIGPIPE, SIGSEGV)
139 | 141) echo "signal" ;;
# Shell errors (general error, syntax error)
# Shell errors (general error, syntax error)
1 | 2) echo "shell" ;;
# Default - truly unknown
@@ -1292,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

@@ -3578,6 +3578,13 @@ build_container() {
# DEV_MODE exports (optional, for debugging)
export BUILD_LOG="$BUILD_LOG"
export INSTALL_LOG="/root/.install-${SESSION_ID}.log"
# Keep host-side logging on BUILD_LOG (not exported — invisible to container)
# Without this, get_active_logfile() would return INSTALL_LOG (a container path)
# and all host msg_info/msg_ok/msg_error would write to /root/.install-SESSION.log
# on the HOST instead of BUILD_LOG, causing incomplete telemetry logs.
_HOST_LOGFILE="$BUILD_LOG"
export dev_mode="${dev_mode:-}"
export DEV_MODE_MOTD="${DEV_MODE_MOTD:-false}"
export DEV_MODE_KEEP="${DEV_MODE_KEEP:-false}"
@@ -3664,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"
# ============================================================================
@@ -3905,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
@@ -3960,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
@@ -4032,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
@@ -4052,11 +4059,26 @@ EOF'
set +Eeuo pipefail # Disable ALL error handling temporarily
trap - ERR # Remove ERR trap completely
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local lxc_exit=$?
# Signal handlers use this flag to stop the container on abort (SIGHUP/SIGINT/SIGTERM)
# Without this, SSH disconnects leave the container running as an orphan process
# that sends "configuring" status AFTER the host already reported "failed"
export CONTAINER_INSTALLING=true
set -Eeuo pipefail # Re-enable error handling
trap 'error_handler' ERR # Restore ERR trap
# 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
# Keep error handling DISABLED during failure detection and recovery
# Re-enabling it here would cause any pct exec/pull failure to trigger
# error_handler() on the host, bypassing the recovery menu entirely
# Check for error flag file in container (more reliable than lxc-attach exit code)
local install_exit_code=0
@@ -4108,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)"
@@ -4116,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
@@ -4378,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
@@ -4484,6 +4533,13 @@ 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
}
destroy_lxc() {
@@ -4891,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]"
@@ -5420,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
}
# ==============================================================================
@@ -5561,9 +5619,13 @@ api_exit_script() {
# ALWAYS send telemetry FIRST - ensure status is reported even if
# ensure_log_on_host hangs (e.g. pct pull on dead container)
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
# Best-effort log collection with timeout (non-critical after telemetry is sent)
# Best-effort log collection (non-critical after telemetry is sent)
if declare -f ensure_log_on_host >/dev/null 2>&1; then
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
ensure_log_on_host 2>/dev/null || true
fi
# Stop orphaned container if we're in the install phase
if [[ "${CONTAINER_INSTALLING:-}" == "true" && -n "${CTID:-}" ]] && command -v pct &>/dev/null; then
pct stop "$CTID" 2>/dev/null || true
fi
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
# Script exited with 0 but never sent a completion status
@@ -5575,7 +5637,7 @@ api_exit_script() {
if command -v pveversion >/dev/null 2>&1; then
trap 'api_exit_script' EXIT
fi
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then post_update_to_api "failed" "$_ec" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; fi' ERR
trap 'post_update_to_api "failed" "129" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 129' SIGHUP
trap 'post_update_to_api "failed" "130" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 130' SIGINT
trap 'post_update_to_api "failed" "143" 2>/dev/null || true; timeout 10 bash -c "ensure_log_on_host" 2>/dev/null || true; exit 143' SIGTERM
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then post_update_to_api "failed" "$_ec" 2>/dev/null || true; if declare -f ensure_log_on_host &>/dev/null; then ensure_log_on_host 2>/dev/null || true; fi; fi' ERR
trap 'post_update_to_api "failed" "129" 2>/dev/null || true; if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null; then pct stop "$CTID" 2>/dev/null || true; fi; exit 129' SIGHUP
trap 'post_update_to_api "failed" "130" 2>/dev/null || true; if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null; then pct stop "$CTID" 2>/dev/null || true; fi; exit 130' SIGINT
trap 'post_update_to_api "failed" "143" 2>/dev/null || true; if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null; then pct stop "$CTID" 2>/dev/null || true; fi; exit 143' SIGTERM

View File

@@ -395,12 +395,20 @@ ssh_check() {
# get_active_logfile()
#
# - Returns the appropriate log file based on execution context
# - BUILD_LOG: Host operations (container creation)
# - _HOST_LOGFILE: Override for host context (keeps host logging on BUILD_LOG
# even after INSTALL_LOG is exported for the container)
# - INSTALL_LOG: Container operations (application installation)
# - BUILD_LOG: Host operations (container creation)
# - Fallback to BUILD_LOG if neither is set
# ------------------------------------------------------------------------------
get_active_logfile() {
if [[ -n "${INSTALL_LOG:-}" ]]; then
# Host override: _HOST_LOGFILE is set (not exported) in build.func to keep
# host-side logging in BUILD_LOG after INSTALL_LOG is exported for the container.
# Without this, all host msg_info/msg_ok/msg_error would write to
# /root/.install-SESSION.log (a container path) instead of BUILD_LOG.
if [[ -n "${_HOST_LOGFILE:-}" ]]; then
echo "$_HOST_LOGFILE"
elif [[ -n "${INSTALL_LOG:-}" ]]; then
echo "$INSTALL_LOG"
elif [[ -n "${BUILD_LOG:-}" ]]; then
echo "$BUILD_LOG"
@@ -480,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
# ------------------------------------------------------------------------------
@@ -522,9 +530,10 @@ silent() {
msg_custom "→" "${YWB}" "${cmd}"
if [[ -s "$logfile" ]]; then
echo -e "\n${TAB}--- Last 10 lines of log ---"
tail -n 10 "$logfile"
echo -e "${TAB}-----------------------------------\n"
echo -e "\n${TAB}--- Last 20 lines of log ---"
tail -n 20 "$logfile"
echo -e "${TAB}-----------------------------------"
echo -e "${TAB}📋 Full log: ${logfile}\n"
fi
exit "$rc"
@@ -1496,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

@@ -208,6 +208,10 @@ error_handler() {
# This ensures we capture failures that occur before/after container exists
if declare -f post_update_to_api &>/dev/null; then
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
else
# Container context: post_update_to_api not available (api.func not sourced)
# Send status directly via curl so container failures are never lost
_send_abort_telemetry "$exit_code" 2>/dev/null || true
fi
# Use msg_error if available, fallback to echo
@@ -236,67 +240,54 @@ error_handler() {
active_log="$SILENT_LOGFILE"
fi
# If active_log points to a container-internal path that doesn't exist on host,
# fall back to BUILD_LOG (host-side log)
if [[ -n "$active_log" && ! -s "$active_log" && -n "${BUILD_LOG:-}" && -s "${BUILD_LOG}" ]]; then
active_log="$BUILD_LOG"
fi
# Show last log lines if available
if [[ -n "$active_log" && -s "$active_log" ]]; then
echo -e "\n${TAB}--- Last 20 lines of log ---"
tail -n 20 "$active_log"
echo -e "${TAB}-----------------------------------\n"
fi
# Detect context: Container (INSTALL_LOG set + /root exists) vs Host (BUILD_LOG)
if [[ -n "${INSTALL_LOG:-}" && -d /root ]]; then
# CONTAINER CONTEXT: Copy log and create flag file for host
local container_log="/root/.install-${SESSION_ID:-error}.log"
cp "$active_log" "$container_log" 2>/dev/null || true
# Detect context: Container (INSTALL_LOG set + inside container /root) vs Host
if [[ -n "${INSTALL_LOG:-}" && -f "${INSTALL_LOG:-}" && -d /root ]]; then
# CONTAINER CONTEXT: Copy log and create flag file for host
local container_log="/root/.install-${SESSION_ID:-error}.log"
cp "${INSTALL_LOG}" "$container_log" 2>/dev/null || true
# Create error flag file with exit code for host detection
echo "$exit_code" >"/root/.install-${SESSION_ID:-error}.failed" 2>/dev/null || true
# Log path is shown by host as combined log - no need to show container path
else
# HOST CONTEXT: Show local log path and offer container cleanup
# Create error flag file with exit code for host detection
echo "$exit_code" >"/root/.install-${SESSION_ID:-error}.failed" 2>/dev/null || true
# Log path is shown by host as combined log - no need to show container path
else
# HOST CONTEXT: Show local log path and offer container cleanup
if [[ -n "$active_log" && -s "$active_log" ]]; then
if declare -f msg_custom >/dev/null 2>&1; then
msg_custom "📋" "${YW}" "Full log: ${active_log}"
else
echo -e "${YW}Full log:${CL} ${BL}${active_log}${CL}"
fi
fi
# Offer to remove container if it exists (build errors after container creation)
if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null && pct status "$CTID" &>/dev/null; then
echo ""
if declare -f msg_custom >/dev/null 2>&1; then
echo -en "${TAB}${TAB}${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
else
echo -en "${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
fi
# Offer to remove container if it exists (build errors after container creation)
if [[ -n "${CTID:-}" ]] && command -v pct &>/dev/null && pct status "$CTID" &>/dev/null; then
echo ""
if declare -f msg_custom >/dev/null 2>&1; then
echo -en "${TAB}${TAB}${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
else
echo -en "${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
fi
if read -t 60 -r response; then
if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then
echo ""
if declare -f msg_info >/dev/null 2>&1; then
msg_info "Removing container ${CTID}"
else
echo -e "${YW}Removing container ${CTID}${CL}"
fi
pct stop "$CTID" &>/dev/null || true
pct destroy "$CTID" &>/dev/null || true
if declare -f msg_ok >/dev/null 2>&1; then
msg_ok "Container ${CTID} removed"
else
echo -e "${GN}${CL} Container ${CTID} removed"
fi
elif [[ "$response" =~ ^[Nn]$ ]]; then
echo ""
if declare -f msg_warn >/dev/null 2>&1; then
msg_warn "Container ${CTID} kept for debugging"
else
echo -e "${YW}Container ${CTID} kept for debugging${CL}"
fi
fi
else
# Timeout - auto-remove
if read -t 60 -r response; then
if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then
echo ""
if declare -f msg_info >/dev/null 2>&1; then
msg_info "No response - removing container ${CTID}"
msg_info "Removing container ${CTID}"
else
echo -e "${YW}No response - removing container ${CTID}${CL}"
echo -e "${YW}Removing container ${CTID}${CL}"
fi
pct stop "$CTID" &>/dev/null || true
pct destroy "$CTID" &>/dev/null || true
@@ -305,13 +296,35 @@ error_handler() {
else
echo -e "${GN}${CL} Container ${CTID} removed"
fi
elif [[ "$response" =~ ^[Nn]$ ]]; then
echo ""
if declare -f msg_warn >/dev/null 2>&1; then
msg_warn "Container ${CTID} kept for debugging"
else
echo -e "${YW}Container ${CTID} kept for debugging${CL}"
fi
fi
else
# Timeout - auto-remove
echo ""
if declare -f msg_info >/dev/null 2>&1; then
msg_info "No response - removing container ${CTID}"
else
echo -e "${YW}No response - removing container ${CTID}${CL}"
fi
pct stop "$CTID" &>/dev/null || true
pct destroy "$CTID" &>/dev/null || true
if declare -f msg_ok >/dev/null 2>&1; then
msg_ok "Container ${CTID} removed"
else
echo -e "${GN}${CL} Container ${CTID} removed"
fi
fi
# Force one final status update attempt after cleanup
# This ensures status is updated even if the first attempt failed (e.g., HTTP 400)
if declare -f post_update_to_api &>/dev/null; then
post_update_to_api "failed" "$exit_code" "force"
fi
# Force one final status update attempt after cleanup
# This ensures status is updated even if the first attempt failed (e.g., HTTP 400)
if declare -f post_update_to_api &>/dev/null; then
post_update_to_api "failed" "$exit_code" "force"
fi
fi
fi
@@ -320,40 +333,97 @@ error_handler() {
}
# ==============================================================================
# SECTION 3: SIGNAL HANDLERS
# SECTION 3: TELEMETRY & CLEANUP HELPERS FOR SIGNAL HANDLERS
# ==============================================================================
# ------------------------------------------------------------------------------
# _send_abort_telemetry()
#
# - Sends failure/abort status to telemetry API
# - Works in BOTH host context (post_update_to_api available) and
# container context (only curl available, api.func not sourced)
# - Container context is critical: without this, container-side failures
# and signal exits are never reported, leaving records stuck in
# "installing" or "configuring" forever
# - Arguments: $1 = exit_code
# ------------------------------------------------------------------------------
_send_abort_telemetry() {
local exit_code="${1:-1}"
# Try full API function first (host context - api.func sourced)
if declare -f post_update_to_api &>/dev/null; then
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
return
fi
# Fallback: direct curl (container context - api.func NOT sourced)
# This is the ONLY way containers can report failures to telemetry
command -v curl &>/dev/null || return 0
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
[[ -z "${RANDOM_UUID:-}" ]] && return 0
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:-lxc}\",\"nsapp\":\"${NSAPP:-${app:-unknown}}\",\"status\":\"failed\",\"exit_code\":${exit_code}}" &>/dev/null || true
}
# ------------------------------------------------------------------------------
# _stop_container_if_installing()
#
# - Stops the LXC container if we're in the install phase
# - Prevents orphaned container processes when the host exits due to a signal
# (SSH disconnect, Ctrl+C, SIGTERM) — without this, the container keeps
# running and may send "configuring" status AFTER the host already sent
# "failed", leaving records permanently stuck in "configuring"
# - Only acts when:
# * CONTAINER_INSTALLING flag is set (during lxc-attach in build_container)
# * CTID is set (container was created)
# * pct command is available (we're on the Proxmox host, not inside a container)
# - Does NOT destroy the container — just stops it for potential debugging
# ------------------------------------------------------------------------------
_stop_container_if_installing() {
[[ "${CONTAINER_INSTALLING:-}" == "true" ]] || return 0
[[ -n "${CTID:-}" ]] || return 0
command -v pct &>/dev/null || return 0
pct stop "$CTID" 2>/dev/null || true
}
# ==============================================================================
# SECTION 4: SIGNAL HANDLERS
# ==============================================================================
# ------------------------------------------------------------------------------
# on_exit()
#
# - EXIT trap handler
# - Cleans up lock files if lockfile variable is set
# - Exits with captured exit code
# - Always runs on script termination (success or failure)
# - For signal exits (>128): sends telemetry FIRST before log collection
# to prevent pct pull hangs from blocking status updates
# - EXIT trap handler — runs on EVERY script termination
# - Catches orphaned "installing"/"configuring" records:
# * If post_to_api sent "installing" but post_update_to_api never ran
# * Reports final status to prevent records stuck forever
# - Best-effort log collection for failed installs
# - Stops orphaned container processes on failure
# - Cleans up lock files
# ------------------------------------------------------------------------------
on_exit() {
local exit_code=$?
# Report orphaned "installing" records to telemetry API
# Catches ALL exit paths: errors (non-zero), signals, AND clean exits where
# post_to_api was called ("installing" sent) but post_update_to_api was never called
# Catches ALL exit paths: errors, signals, AND clean exits where
# post_to_api was called but post_update_to_api was never called
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if declare -f post_update_to_api >/dev/null 2>&1; then
# ALWAYS send telemetry FIRST - ensure status is reported even if
# ensure_log_on_host hangs (e.g. pct pull on dead/unresponsive container)
if [[ $exit_code -ne 0 ]]; then
post_update_to_api "failed" "$exit_code" 2>/dev/null || true
else
# exit_code=0 is never an error — report as success
post_update_to_api "done" "0" 2>/dev/null || true
fi
# Best-effort log collection with timeout (non-critical after telemetry is sent)
if declare -f ensure_log_on_host >/dev/null 2>&1; then
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
fi
if [[ $exit_code -ne 0 ]]; then
_send_abort_telemetry "$exit_code"
elif declare -f post_update_to_api >/dev/null 2>&1; then
post_update_to_api "done" "0" 2>/dev/null || true
fi
fi
# Best-effort log collection on failure (non-critical, telemetry already sent)
if [[ $exit_code -ne 0 ]] && declare -f ensure_log_on_host >/dev/null 2>&1; then
ensure_log_on_host 2>/dev/null || true
fi
# Stop orphaned container if we're in the install phase and exiting with error
if [[ $exit_code -ne 0 ]]; then
_stop_container_if_installing
fi
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
exit "$exit_code"
}
@@ -362,22 +432,13 @@ on_exit() {
# on_interrupt()
#
# - SIGINT (Ctrl+C) trap handler
# - Reports to telemetry FIRST (time-critical: container may be dying)
# - Displays "Interrupted by user" message
# - Reports status FIRST (time-critical: container may be dying)
# - Stops orphaned container to prevent "configuring" ghost records
# - Exits with code 130 (128 + SIGINT=2)
# - Output redirected to /dev/null fallback to prevent SIGPIPE on closed terminals
# ------------------------------------------------------------------------------
on_interrupt() {
# CRITICAL: Send telemetry FIRST before any cleanup or output
# If ensure_log_on_host hangs (e.g. pct pull on dying container),
# the status update would never be sent, leaving records stuck in "installing"
if declare -f post_update_to_api >/dev/null 2>&1; then
post_update_to_api "failed" "130" 2>/dev/null || true
fi
# Best-effort log collection with timeout (non-critical after telemetry is sent)
if declare -f ensure_log_on_host >/dev/null 2>&1; then
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
fi
_send_abort_telemetry "130"
_stop_container_if_installing
if declare -f msg_error >/dev/null 2>&1; then
msg_error "Interrupted by user (SIGINT)" 2>/dev/null || true
else
@@ -390,23 +451,13 @@ on_interrupt() {
# on_terminate()
#
# - SIGTERM trap handler
# - Reports to telemetry FIRST (time-critical: process being killed)
# - Displays "Terminated by signal" message
# - Reports status FIRST (time-critical: process being killed)
# - Stops orphaned container to prevent "configuring" ghost records
# - Exits with code 143 (128 + SIGTERM=15)
# - Triggered by external process termination
# - Output redirected to /dev/null fallback to prevent SIGPIPE on closed terminals
# ------------------------------------------------------------------------------
on_terminate() {
# CRITICAL: Send telemetry FIRST before any cleanup or output
# Same rationale as on_interrupt: ensure status gets reported even if
# ensure_log_on_host hangs or terminal is already closed
if declare -f post_update_to_api >/dev/null 2>&1; then
post_update_to_api "failed" "143" 2>/dev/null || true
fi
# Best-effort log collection with timeout (non-critical after telemetry is sent)
if declare -f ensure_log_on_host >/dev/null 2>&1; then
timeout 10 bash -c 'ensure_log_on_host' 2>/dev/null || true
fi
_send_abort_telemetry "143"
_stop_container_if_installing
if declare -f msg_error >/dev/null 2>&1; then
msg_error "Terminated by signal (SIGTERM)" 2>/dev/null || true
else
@@ -415,8 +466,25 @@ on_terminate() {
exit 143
}
# ------------------------------------------------------------------------------
# on_hangup()
#
# - SIGHUP trap handler (SSH disconnect, terminal closed)
# - CRITICAL: This was previously MISSING from catch_errors(), causing
# container processes to become orphans on SSH disconnect — the #1 cause
# of records stuck in "installing" and "configuring" states
# - Reports status via direct curl (terminal is already closed, no output)
# - Stops orphaned container to prevent ghost records
# - Exits with code 129 (128 + SIGHUP=1)
# ------------------------------------------------------------------------------
on_hangup() {
_send_abort_telemetry "129"
_stop_container_if_installing
exit 129
}
# ==============================================================================
# SECTION 4: INITIALIZATION
# SECTION 5: INITIALIZATION
# ==============================================================================
# ------------------------------------------------------------------------------
@@ -428,10 +496,11 @@ on_terminate() {
# * set -o pipefail: Pipeline fails if any command fails
# * set -u: (optional) Exit on undefined variable (if STRICT_UNSET=1)
# - Sets up traps:
# * ERR → error_handler
# * EXIT → on_exit
# * INT → on_interrupt
# * TERM → on_terminate
# * ERR → error_handler (script errors)
# * EXIT → on_exit (any termination — cleanup + orphan detection)
# * INT → on_interrupt (Ctrl+C)
# * TERM → on_terminate (kill / systemd stop)
# * HUP → on_hangup (SSH disconnect / terminal closed)
# - Call this function early in every script
# ------------------------------------------------------------------------------
catch_errors() {
@@ -444,4 +513,5 @@ catch_errors() {
trap on_exit EXIT
trap on_interrupt INT
trap on_terminate TERM
trap on_hangup HUP
}

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

@@ -1306,7 +1306,7 @@ setup_deb822_repo() {
if grep -q "BEGIN PGP" "$tmp_gpg" 2>/dev/null; then
# ASCII-armored — dearmor to binary
gpg --dearmor --yes -o "/etc/apt/keyrings/${name}.gpg" < "$tmp_gpg" || {
gpg --dearmor --yes -o "/etc/apt/keyrings/${name}.gpg" <"$tmp_gpg" || {
msg_error "Failed to dearmor GPG key for ${name}"
rm -f "$tmp_gpg"
return 1
@@ -1567,31 +1567,54 @@ check_for_gh_release() {
ensure_dependencies jq
# Build auth header if token is available
local header_args=()
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
# Try /latest endpoint for non-pinned versions (most efficient)
local releases_json=""
local releases_json="" http_code=""
if [[ -z "$pinned_version_in" ]]; then
releases_json=$(curl -fsSL --max-time 20 \
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_check.json \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"https://api.github.com/repos/${source}/releases/latest" 2>/dev/null)
"${header_args[@]}" \
"https://api.github.com/repos/${source}/releases/latest" 2>/dev/null) || true
if [[ $? -eq 0 ]] && [[ -n "$releases_json" ]]; then
# Wrap single release in array for consistent processing
releases_json="[$releases_json]"
if [[ "$http_code" == "200" ]] && [[ -s /tmp/gh_check.json ]]; then
releases_json="[$(</tmp/gh_check.json)]"
elif [[ "$http_code" == "403" ]]; then
msg_error "GitHub API rate limit exceeded (HTTP 403)."
msg_error "To increase the limit, export a GitHub token before running the script:"
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
rm -f /tmp/gh_check.json
return 1
fi
rm -f /tmp/gh_check.json
fi
# If no releases yet (pinned version OR /latest failed), fetch up to 100
if [[ -z "$releases_json" ]]; then
# Fetch releases and exclude drafts/prereleases
releases_json=$(curl -fsSL --max-time 20 \
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_check.json \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"https://api.github.com/repos/${source}/releases?per_page=100") || {
msg_error "Unable to fetch releases for ${app}"
"${header_args[@]}" \
"https://api.github.com/repos/${source}/releases?per_page=100" 2>/dev/null) || true
if [[ "$http_code" == "200" ]] && [[ -s /tmp/gh_check.json ]]; then
releases_json=$(</tmp/gh_check.json)
elif [[ "$http_code" == "403" ]]; then
msg_error "GitHub API rate limit exceeded (HTTP 403)."
msg_error "To increase the limit, export a GitHub token before running the script:"
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
rm -f /tmp/gh_check.json
return 1
}
else
msg_error "Unable to fetch releases for ${app} (HTTP ${http_code})"
rm -f /tmp/gh_check.json
return 1
fi
rm -f /tmp/gh_check.json
fi
mapfile -t raw_tags < <(jq -r '.[] | select(.draft==false and .prerelease==false) | .tag_name' <<<"$releases_json")
@@ -2410,7 +2433,11 @@ _gh_scan_older_releases() {
# Check with explicit pattern first, then arch heuristic, then any .deb
if [[ -n "$asset_pattern" ]]; then
has_match=$(echo "$releases_list" | jq -r --arg pat "$asset_pattern" ".[$i].assets[].name" | while read -r name; do
case "$name" in $asset_pattern) echo true; break ;; esac
case "$name" in $asset_pattern)
echo true
break
;;
esac
done)
fi
if [[ "$has_match" != "true" ]]; then
@@ -2422,7 +2449,11 @@ _gh_scan_older_releases() {
elif [[ "$mode" == "prebuild" || "$mode" == "singlefile" ]]; then
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].name" | while read -r name; do
case "$name" in $asset_pattern) echo true; break ;; esac
case "$name" in $asset_pattern)
echo true
break
;;
esac
done)
fi
@@ -2481,25 +2512,36 @@ function fetch_and_deploy_gh_release() {
return 1
fi
local max_retries=3 retry_delay=2 attempt=1 success=false resp http_code
local max_retries=3 retry_delay=2 attempt=1 success=false http_code
while ((attempt <= max_retries)); do
resp=$(curl $api_timeout -fsSL -w "%{http_code}" -o /tmp/gh_rel.json "${header[@]}" "$api_url") && success=true && break
sleep "$retry_delay"
http_code=$(curl $api_timeout -sSL -w "%{http_code}" -o /tmp/gh_rel.json "${header[@]}" "$api_url" 2>/dev/null) || true
if [[ "$http_code" == "200" ]]; then
success=true
break
elif [[ "$http_code" == "403" ]]; then
if ((attempt < max_retries)); then
msg_warn "GitHub API rate limit hit, retrying in ${retry_delay}s... (attempt $attempt/$max_retries)"
sleep "$retry_delay"
retry_delay=$((retry_delay * 2))
fi
else
sleep "$retry_delay"
fi
((attempt++))
done
if ! $success; then
msg_error "Failed to fetch release metadata from $api_url after $max_retries attempts"
if [[ "$http_code" == "403" ]]; then
msg_error "GitHub API rate limit exceeded (HTTP 403)."
msg_error "To increase the limit, export a GitHub token before running the script:"
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
else
msg_error "Failed to fetch release metadata from $api_url after $max_retries attempts (HTTP $http_code)"
fi
return 1
fi
http_code="${resp:(-3)}"
[[ "$http_code" != "200" ]] && {
msg_error "GitHub API returned HTTP $http_code"
return 1
}
local json tag_name
json=$(</tmp/gh_rel.json)
tag_name=$(echo "$json" | jq -r '.tag_name // .name // empty')
@@ -2599,12 +2641,19 @@ function fetch_and_deploy_gh_release() {
assets=$(echo "$json" | jq -r '.assets[].browser_download_url')
if [[ -n "$asset_pattern" ]]; then
for u in $assets; do
case "${u##*/}" in $asset_pattern) url_match="$u"; break ;; esac
case "${u##*/}" in $asset_pattern)
url_match="$u"
break
;;
esac
done
fi
if [[ -z "$url_match" ]]; then
for u in $assets; do
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then url_match="$u"; break; fi
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then
url_match="$u"
break
fi
done
fi
if [[ -z "$url_match" ]]; then
@@ -2673,7 +2722,11 @@ function fetch_and_deploy_gh_release() {
msg_info "Fetching GitHub release: $app ($version)"
for u in $(echo "$json" | jq -r '.assets[].browser_download_url'); do
filename_candidate="${u##*/}"
case "$filename_candidate" in $pattern) asset_url="$u"; break ;; esac
case "$filename_candidate" in $pattern)
asset_url="$u"
break
;;
esac
done
fi
fi
@@ -2785,7 +2838,11 @@ function fetch_and_deploy_gh_release() {
msg_info "Fetching GitHub release: $app ($version)"
for u in $(echo "$json" | jq -r '.assets[].browser_download_url'); do
filename_candidate="${u##*/}"
case "$filename_candidate" in $pattern) asset_url="$u"; break ;; esac
case "$filename_candidate" in $pattern)
asset_url="$u"
break
;;
esac
done
fi
fi
@@ -3635,20 +3692,22 @@ _setup_intel_arc() {
# Add non-free repos
_add_debian_nonfree "$os_codename"
# Arc requires latest drivers - fetch from GitHub
# Order matters: libigdgmm first (dependency), then IGC, then compute-runtime
msg_info "Fetching Intel compute-runtime for Arc support"
# For Trixie/Sid: Fetch latest drivers from GitHub (Debian repo packages may be too old or missing)
# For Bookworm: Use repo packages (GitHub latest requires libstdc++6 >= 13.1, unavailable on Bookworm)
if [[ "$os_codename" == "trixie" || "$os_codename" == "sid" ]]; then
msg_info "Fetching Intel compute-runtime from GitHub for Arc support"
# libigdgmm - bundled in compute-runtime releases (Debian version often too old)
fetch_and_deploy_gh_release "libigdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || true
# libigdgmm - bundled in compute-runtime releases
fetch_and_deploy_gh_release "libigdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || true
# Intel Graphics Compiler (note: packages have -2 suffix)
fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || true
fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || true
# Intel Graphics Compiler (note: packages have -2 suffix)
fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || true
fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || true
# Compute Runtime (depends on IGC and gmmlib)
fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || true
fetch_and_deploy_gh_release "intel-level-zero-gpu" "intel/compute-runtime" "binary" "latest" "" "libze-intel-gpu1_*_amd64.deb" || true
# Compute Runtime (depends on IGC and gmmlib)
fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || true
fetch_and_deploy_gh_release "intel-level-zero-gpu" "intel/compute-runtime" "binary" "latest" "" "libze-intel-gpu1_*_amd64.deb" || true
fi
$STD apt -y install \
intel-media-va-driver-non-free \
@@ -3657,6 +3716,9 @@ _setup_intel_arc() {
libmfx-gen1.2 \
vainfo \
intel-gpu-tools 2>/dev/null || msg_warn "Some Intel Arc packages failed"
# Bookworm has compatible versions of these packages in repos
[[ "$os_codename" == "bookworm" ]] && $STD apt -y install intel-opencl-icd libigdgmm12 2>/dev/null || true
fi
msg_ok "Intel Arc GPU configured"
@@ -4028,6 +4090,7 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: bullseye bullseye-updates
Components: non-free
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
bookworm)
@@ -4036,6 +4099,7 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: bookworm bookworm-updates
Components: non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
trixie | sid)
@@ -4044,11 +4108,13 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
Components: non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian-security
Suites: trixie-security
Components: non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
esac
@@ -4071,11 +4137,13 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: bullseye bullseye-updates
Components: non-free
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian-security
Suites: bullseye-security
Components: non-free
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
bookworm)
@@ -4084,11 +4152,13 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: bookworm bookworm-updates
Components: non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian-security
Suites: bookworm-security
Components: non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
trixie | sid)
@@ -4097,11 +4167,13 @@ Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
Components: non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://deb.debian.org/debian-security
Suites: trixie-security
Components: non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
;;
esac
@@ -4609,8 +4681,8 @@ EOF
# First, check if there's an old/broken repository that needs cleanup
if [[ -f /etc/apt/sources.list.d/mariadb.sources ]] || [[ -f /etc/apt/sources.list.d/mariadb.list ]]; then
local OLD_REPO_VERSION=""
OLD_REPO_VERSION=$(grep -oP 'repo/\K[0-9]+\.[0-9]+(\.[0-9]+)?' /etc/apt/sources.list.d/mariadb.sources 2>/dev/null || \
grep -oP 'repo/\K[0-9]+\.[0-9]+(\.[0-9]+)?' /etc/apt/sources.list.d/mariadb.list 2>/dev/null || echo "")
OLD_REPO_VERSION=$(grep -oP 'repo/\K[0-9]+\.[0-9]+(\.[0-9]+)?' /etc/apt/sources.list.d/mariadb.sources 2>/dev/null ||
grep -oP 'repo/\K[0-9]+\.[0-9]+(\.[0-9]+)?' /etc/apt/sources.list.d/mariadb.list 2>/dev/null || echo "")
# Check if old repo points to a different version
if [[ -n "$OLD_REPO_VERSION" ]] && [[ "${OLD_REPO_VERSION%.*}" != "${MARIADB_VERSION%.*}" ]]; then
@@ -5510,7 +5582,7 @@ EOF
# Try to install each package individually
for pkg in $MODULE_LIST; do
[[ "$pkg" == "php${PHP_VERSION}" ]] && continue # Already installed
[[ "$pkg" == "php${PHP_VERSION}" ]] && continue # Already installed
$STD apt install -y "$pkg" 2>/dev/null || {
msg_warn "Could not install $pkg - continuing without it"
}
@@ -6120,14 +6192,14 @@ function setup_meilisearch() {
local MAX_WAIT=120
local WAITED=0
local TASK_RESULT=""
while [[ $WAITED -lt $MAX_WAIT ]]; do
TASK_RESULT=$(curl -s "http://${MEILI_HOST}:${MEILI_PORT}/tasks/${TASK_UID}" \
-H "Authorization: Bearer ${MEILI_MASTER_KEY}" 2>/dev/null) || true
local TASK_STATUS
TASK_STATUS=$(echo "$TASK_RESULT" | grep -oP '"status":\s*"\K[^"]+' || true)
if [[ "$TASK_STATUS" == "succeeded" ]]; then
# Extract dumpUid from the completed task details
DUMP_UID=$(echo "$TASK_RESULT" | grep -oP '"dumpUid":\s*"\K[^"]+' || true)
@@ -6165,7 +6237,7 @@ function setup_meilisearch() {
local MEILI_DB_PATH
MEILI_DB_PATH=$(grep -E "^db_path\s*=" /etc/meilisearch.toml 2>/dev/null | sed 's/.*=\s*"\(.*\)"/\1/' | tr -d ' ')
MEILI_DB_PATH="${MEILI_DB_PATH:-/var/lib/meilisearch/data}"
if [[ -d "$MEILI_DB_PATH" ]] && [[ -n "$(ls -A "$MEILI_DB_PATH" 2>/dev/null)" ]]; then
local BACKUP_PATH="${MEILI_DB_PATH}.backup.$(date +%Y%m%d%H%M%S)"
msg_warn "Backing up MeiliSearch data to ${BACKUP_PATH}"
@@ -6193,12 +6265,12 @@ function setup_meilisearch() {
local DUMP_FILE="${MEILI_DUMP_DIR}/${DUMP_UID}.dump"
if [[ -f "$DUMP_FILE" ]]; then
msg_info "Importing dump: ${DUMP_FILE}"
# Start meilisearch with --import-dump flag
# This is a one-time import that happens during startup
/usr/bin/meilisearch --config-file-path /etc/meilisearch.toml --import-dump "$DUMP_FILE" &
local MEILI_PID=$!
# Wait for meilisearch to become healthy (import happens during startup)
msg_info "Waiting for MeiliSearch to import and start..."
local MAX_WAIT=300
@@ -6216,14 +6288,14 @@ function setup_meilisearch() {
sleep 3
WAITED=$((WAITED + 3))
done
# Stop the manual process
kill $MEILI_PID 2>/dev/null || true
sleep 2
# Start via systemd for proper management
systemctl start meilisearch
if systemctl is-active --quiet meilisearch; then
msg_ok "MeiliSearch migrated successfully"
else
@@ -6311,14 +6383,14 @@ EOF
MEILISEARCH_API_KEY=""
for i in {1..10}; do
MEILISEARCH_API_KEY=$(curl -s -X GET "http://${MEILISEARCH_HOST}:${MEILISEARCH_PORT}/keys" \
-H "Authorization: Bearer ${MEILISEARCH_MASTER_KEY}" 2>/dev/null | \
-H "Authorization: Bearer ${MEILISEARCH_MASTER_KEY}" 2>/dev/null |
grep -o '"key":"[^"]*"' | head -n 1 | sed 's/"key":"//;s/"//') || true
[[ -n "$MEILISEARCH_API_KEY" ]] && break
sleep 2
done
MEILISEARCH_API_KEY_UID=$(curl -s -X GET "http://${MEILISEARCH_HOST}:${MEILISEARCH_PORT}/keys" \
-H "Authorization: Bearer ${MEILISEARCH_MASTER_KEY}" 2>/dev/null | \
-H "Authorization: Bearer ${MEILISEARCH_MASTER_KEY}" 2>/dev/null |
grep -o '"uid":"[^"]*"' | head -n 1 | sed 's/"uid":"//;s/"//') || true
export MEILISEARCH_API_KEY
@@ -7104,9 +7176,9 @@ function fetch_and_deploy_from_url() {
# Auto-detect archive type using file description
local file_desc
file_desc=$(file -b "$tmpdir/$filename")
local archive_type="unknown"
if [[ "$file_desc" =~ gzip.*compressed|gzip\ compressed\ data ]]; then
archive_type="tar"
elif [[ "$file_desc" =~ Zip.*archive|ZIP\ archive ]]; then

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

229
tools/addon/cronmaster.sh Normal file
View File

@@ -0,0 +1,229 @@
#!/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/fccview/cronmaster
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
load_functions
init_tool_telemetry "" "addon"
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="CronMaster"
APP_TYPE="addon"
INSTALL_PATH="/opt/cronmaster"
CONFIG_PATH="/opt/cronmaster/.env"
SERVICE_PATH="/etc/systemd/system/cronmaster.service"
DEFAULT_PORT=3000
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
______ __ ___ __
/ ____/________ ____ / |/ /___ ______/ /____ _____
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/
EOF
}
# ==============================================================================
# OS DETECTION
# ==============================================================================
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
exit 1
fi
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
systemctl disable --now cronmaster.service &>/dev/null || true
rm -f "$SERVICE_PATH"
rm -rf "$INSTALL_PATH"
rm -f "/usr/local/bin/update_cronmaster"
rm -f "$HOME/.cronmaster"
rm -f "/root/cronmaster.creds"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
if check_for_gh_release "cronmaster" "fccview/cronmaster"; then
msg_info "Stopping service"
systemctl stop cronmaster.service &>/dev/null || true
msg_ok "Stopped service"
msg_info "Backing up configuration"
cp "$CONFIG_PATH" /tmp/cronmaster.env.bak 2>/dev/null || true
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
msg_info "Restoring configuration"
cp /tmp/cronmaster.env.bak "$CONFIG_PATH" 2>/dev/null || true
rm -f /tmp/cronmaster.env.bak
msg_ok "Restored configuration"
msg_info "Starting service"
systemctl start cronmaster
msg_ok "Started service"
msg_ok "Updated successfully"
exit
fi
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
# Setup Node.js (only installs if not present or different version)
if command -v node &>/dev/null; then
msg_ok "Node.js already installed ($(node -v))"
else
NODE_VERSION="22" setup_nodejs
fi
fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
local AUTH_PASS
AUTH_PASS="$(openssl rand -base64 18 | cut -c1-13)"
msg_info "Creating configuration"
cat <<EOF >"$CONFIG_PATH"
NODE_ENV=production
AUTH_PASSWORD=${AUTH_PASS}
PORT=${DEFAULT_PORT}
HOSTNAME=0.0.0.0
NEXT_TELEMETRY_DISABLED=1
EOF
chmod 600 "$CONFIG_PATH"
msg_ok "Created configuration"
msg_info "Creating service"
cat <<EOF >"$SERVICE_PATH"
[Unit]
Description=CronMaster Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=${INSTALL_PATH}
EnvironmentFile=${CONFIG_PATH}
ExecStart=/usr/bin/node ${INSTALL_PATH}/server.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now cronmaster
msg_ok "Created and started service"
# Create update script
msg_info "Creating update script"
ensure_usr_local_bin_persist
cat <<EOF >/usr/local/bin/update_cronmaster
#!/usr/bin/env bash
# CronMaster Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/cronmaster.sh)"
EOF
chmod +x /usr/local/bin/update_cronmaster
msg_ok "Created update script (/usr/local/bin/update_cronmaster)"
# Save credentials
local CREDS_FILE="/root/cronmaster.creds"
cat <<EOF >"$CREDS_FILE"
CronMaster Credentials
======================
Password: ${AUTH_PASS}
Web UI: http://${LOCAL_IP}:${DEFAULT_PORT}
EOF
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
msg_ok "Credentials saved to: ${BL}${CREDS_FILE}${CL}"
echo ""
}
# ==============================================================================
# MAIN
# ==============================================================================
header_info
ensure_usr_local_bin_persist
get_lxc_ip
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
fi
exit 0
fi
# Check if already installed
if [[ -d "$INSTALL_PATH" && -n "$(ls -A "$INSTALL_PATH" 2>/dev/null)" ]]; 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} - Node.js 22"
echo -e "${TAB} - CronMaster (prebuild)"
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/cronmaster Normal file
View File

@@ -0,0 +1,6 @@
______ __ ___ __
/ ____/________ ____ / |/ /___ ______/ /____ _____
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/

View File

@@ -12,6 +12,7 @@ function header_info() {
/ / / / _ \/ __ `/ __ \ / / | / /
/ /___/ / __/ /_/ / / / / / /___/ / /___
\____/_/\___/\__,_/_/ /_/ /_____/_/|_\____/
EOF
}
@@ -74,10 +75,10 @@ function run_lxc_clean() {
find /var/cache -type f -delete 2>/dev/null
find /var/log -type f -delete 2>/dev/null
find /tmp -mindepth 1 -delete 2>/dev/null
apt-get -y --purge autoremove
apt-get -y autoclean
apt -y --purge autoremove
apt -y autoclean
rm -rf /var/lib/apt/lists/*
apt-get update
apt update
fi
'
}

View File

@@ -63,8 +63,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -63,8 +63,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -63,8 +63,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -37,8 +37,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
@@ -525,9 +526,9 @@ fi
msg_info "Finalizing image (hostname, SSH config)"
# Set hostname and prepare for unique machine-id
virt-customize -q -a "$WORK_FILE" --hostname "${HN}" >/dev/null 2>&1
virt-customize -q -a "$WORK_FILE" --run-command "truncate -s 0 /etc/machine-id" >/dev/null 2>&1
virt-customize -q -a "$WORK_FILE" --run-command "rm -f /var/lib/dbus/machine-id" >/dev/null 2>&1
virt-customize -q -a "$WORK_FILE" --hostname "${HN}" >/dev/null 2>&1 || true
virt-customize -q -a "$WORK_FILE" --run-command "truncate -s 0 /etc/machine-id" >/dev/null 2>&1 || true
virt-customize -q -a "$WORK_FILE" --run-command "rm -f /var/lib/dbus/machine-id" >/dev/null 2>&1 || true
# Configure SSH for Cloud-Init
if [ "$USE_CLOUD_INIT" = "yes" ]; then
@@ -552,7 +553,7 @@ msg_ok "Finalized image"
# Create first-boot Docker install script (fallback if virt-customize failed)
if [ "$DOCKER_PREINSTALLED" = "no" ]; then
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /root/install-docker.sh << "DOCKERSCRIPT"
if virt-customize -q -a "$WORK_FILE" --run-command 'cat > /root/install-docker.sh << "DOCKERSCRIPT"
#!/bin/bash
exec > /var/log/install-docker.log 2>&1
echo "[$(date)] Starting Docker installation"
@@ -581,9 +582,9 @@ systemctl restart docker
touch /root/.docker-installed
echo "[$(date)] Docker installation completed"
DOCKERSCRIPT
chmod +x /root/install-docker.sh' >/dev/null 2>&1
chmod +x /root/install-docker.sh' >/dev/null 2>&1; then
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/install-docker.service << "DOCKERSERVICE"
virt-customize -q -a "$WORK_FILE" --run-command 'cat > /etc/systemd/system/install-docker.service << "DOCKERSERVICE"
[Unit]
Description=Install Docker on First Boot
After=network-online.target
@@ -598,7 +599,11 @@ RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
DOCKERSERVICE
systemctl enable install-docker.service' >/dev/null 2>&1
systemctl enable install-docker.service' >/dev/null 2>&1 || true
else
msg_warn "virt-customize failed for this image. Docker must be installed manually after first boot:"
msg_warn " curl -fsSL https://get.docker.com | sh"
fi
fi
# Resize disk to target size

View File

@@ -67,8 +67,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -64,8 +64,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -63,8 +63,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -68,8 +68,9 @@ CLOUD="${TAB}☁️${TAB}${CL}"
set -Eeo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -44,6 +44,9 @@ CROSS="${RD}✗${CL}"
set -Eeo pipefail
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -64,8 +64,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -72,8 +72,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -62,8 +62,9 @@ CLOUD="${TAB}☁️${TAB}${CL}"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -60,8 +60,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -63,8 +63,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -62,8 +62,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"

View File

@@ -62,8 +62,9 @@ THIN="discard=on,ssd=1,"
set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT
trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT
trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM
trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"