Compare commits

...

51 Commits

Author SHA1 Message Date
github-actions[bot]
fe20476c07 chore: update github-versions.json 2026-03-02 13:48:26 +00:00
Michel Roegl-Brunner
5c246310f4 Workflow test 2026-03-02 14:46:46 +01:00
Michel Roegl-Brunner
bdad2cc941 Add workflow to push json changes to pocketbase 2026-03-02 14:46:31 +01:00
community-scripts-pr-app[bot]
f23c33fee7 Update CHANGELOG.md (#12478)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 13:43:06 +00:00
durzo
5b207cf5bd Tracearr: prepare for imminent v1.4.19 release (#12413)
* Tracearr: prepare for upcoming v1.4.19

* remove read prompts, per review
2026-03-02 14:42:39 +01:00
community-scripts-pr-app[bot]
f20c9e4ec9 Update CHANGELOG.md (#12477)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 13:41:55 +00:00
CanbiZ (MickLesk)
1398ff8397 Frigate: Bump to v0.17 (#12474) 2026-03-02 14:41:25 +01:00
CanbiZ (MickLesk)
ebc3512f50 fix: improve error trace propagation for telemetry
- post_update_to_api: Attempts 2/3 now send medium_error (16KB truncated
  log) instead of short_error (generic description only). This is the
  primary fix — when attempt 1 fails (120KB payload too large/timeout),
  attempts 2/3 no longer discard all log data.

- _send_abort_telemetry: Increased container fallback from 20 to 200
  log lines (capped at 16KB). Added SILENT_LOGFILE as fallback source.
  Added exit code explanation header and error_category to payload.

- get_error_text/get_full_log: Added SILENT_LOGFILE as last-resort
  fallback when INSTALL_LOG, combined log, and BUILD_LOG are all
  empty/missing.
2026-03-02 14:38:55 +01:00
Michel Roegl-Brunner
564a8136a5 Workflow test 2026-03-02 14:38:01 +01:00
Michel Roegl-Brunner
00047c95b8 Add workflow to push json changes to pocketbase 2026-03-02 14:37:50 +01:00
Michel Roegl-Brunner
9849ce79a7 Workflow test 2026-03-02 14:36:14 +01:00
Michel Roegl-Brunner
cea9858193 Add workflow to push json changes to pocketbase 2026-03-02 14:36:02 +01:00
Michel Roegl-Brunner
ee8ea672ef Workflow test 2026-03-02 14:33:35 +01:00
Michel Roegl-Brunner
fc59910bd2 Add workflow to push json changes to pocketbase 2026-03-02 14:15:44 +01:00
community-scripts-pr-app[bot]
20ab7bc005 Update CHANGELOG.md (#12476)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 12:58:07 +00:00
CanbiZ (MickLesk)
17de8e761b fix: replace generic exit 1 with specific exit codes in ct/ and install/ scripts (#12475)
Part of #12467 — scripts only (no framework changes).

New exit codes 250-254 registered in api.func and error_handler.func:
- 250: App download failed or version not determined
- 251: App file extraction failed (corrupt/incomplete archive)
- 252: App required file or resource not found
- 253: App data migration required — update aborted
- 254: App user declined prompt or input timed out

Existing codes reused where applicable:
- 10: privileged/Docker required (unifi-os-server)
- 64: invalid user input (postgresql, tomcat)
- 71: system error (pulse useradd)
- 150: service failed to start (docker, npmplus)
- 153: build failed (booklore)
- 233: app not installed (evcc, endurain, grafana, loki, itsm-ng)
- 236: hardware not detected (unifi-os-server /dev/net/tun)
- 238: OS not supported (frigate)
2026-03-02 13:57:42 +01:00
community-scripts-pr-app[bot]
ab1e1cc66e chore: update github-versions.json (#12473)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 12:12:31 +00:00
community-scripts-pr-app[bot]
256143af42 Update CHANGELOG.md (#12471)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 09:56:01 +00:00
CanbiZ (MickLesk)
5dc244a8c1 core: standardize exit codes and add mappings (#12467)
* Standardize exit codes and add mappings

Replace generic exit 1 usages with specific numeric exit codes and add corresponding explanations to the error lookup. This commit updates multiple misc/* scripts to return distinct codes for validation, Proxmox/LXC, networking, download and curl errors (e.g. 103-123, 64, 107-120, 206, 0 for explicit user cancels). It also updates curl error handling to propagate the original curl exit code and adds new entries in explain_exit_code and the error handler to improve diagnostics.

* Set exit code 115 for update_os errors

Change exit status from 6 to 115 in misc/alpine-install.func's update_os() error handlers when failing to download tools.func or when the expected functions are missing. This gives a distinct exit code for these specific failure cases.

* Add tools/addon exit codes and use them

Introduce exit codes 232-238 for Tools & Addon scripts in misc/api.func and misc/error_handler.func. Update addon scripts (tools/addon/adguardhome-sync.sh, tools/addon/copyparty.sh, tools/addon/cronmaster.sh) to return specific codes instead of generic exit 1: 238 for unsupported OS and 233 when the application is not installed/upgrade prerequisites are missing. This makes failures more descriptive and aligns scripts with the central error explanations.

* Standardize exit codes in exporter addons

Unify exit codes across exporter addon scripts: return 238 for unsupported OS detections and 233 when an update is requested but the exporter is not installed. Applied to nextcloud-exporter.sh, pihole-exporter.sh, prometheus-paperless-ngx-exporter.sh, and qbittorrent-exporter.sh to make failure modes distinguishable for callers/automation.

* Use specific exit codes in addon scripts

Replace generic exit 1 with distinct exit codes across multiple addon scripts to enable finer-grained error handling in automation. Exit codes introduced: 10 for Docker/Compose missing or user-declined Docker install, 233 for "nothing to update" cases, and 238 for unsupported OS cases. Affected files: tools/addon/arcane.sh, coolify.sh, dockge.sh, dokploy.sh, filebrowser-quantum.sh, filebrowser.sh, immich-public-proxy.sh, jellystat.sh, runtipi.sh.

* Use specific exit codes in addon scripts

Replace generic exit 1 with specific exit codes across multiple addon scripts to improve error signaling and handling. Files updated: tools/addon/add-netbird-lxc.sh (exit 238 on unsupported distro), tools/addon/add-tailscale-lxc.sh (treat user cancel as exit 0), tools/addon/glances.sh (exit 233 when not installed), tools/addon/komodo.sh (distinct exits for missing compose, legacy DB, backup/download failures, docker checks), tools/addon/netdata.sh (distinct exits for unsupported PVE versions, OS/codename detection, repo lookups), and tools/addon/phpmyadmin.sh (distinct exits for unsupported OS, network/download issues, package install/start failures, and invalid input). These changes make failures easier to identify and automate recovery or reporting.

* Use specific exit codes in PVE scripts

Replace generic exit 1 with distinct exit codes across tools/pve scripts to provide clearer failure signals for callers. post-pve-install.sh now returns 105 for unsupported Proxmox versions; pve-privilege-converter.sh uses 104 for non-root, 234 when no containers, and 235 for backup/conversion failures; update-apps.sh maps backup failures to 235, missing containers/selections to 234 (and UI cancellations to 0), missing backup storage to 119, and returns the actual container update exit code on failure. These changes improve diagnostics and allow external tooling to react to specific error conditions.

* Standardize exit codes and behaviors

Adjust exit codes and abort handling across multiple PVE helper scripts to provide clearer outcomes for automation and interactive flows. Changes include:

- container-restore-from-backup.sh, core-restore-from-backup.sh: return 235 when no backups found (was 1).
- fstrim.sh: treat user cancellation of non-ext4 warning as non-error (exit 0 instead of 1).
- kernel-clean.sh: treat no selection or user abort as non-error (exit 0 instead of 1).
- lxc-delete.sh: return 234 when no containers are present; treat no selection as non-error (exit 0).
- nic-offloading-fix.sh: use specific non-zero codes for root check and tool install failures (exit 104, 237) and 236 when no matching interfaces (was 1).
- pbs_microcode.sh, post-pmg-install.sh, post-pbs-install.sh: use distinct exit codes (232 and 105) for detected VM/PVE/unsupported distro conditions instead of generic 1.

These modifications make scripts return distinct codes for different failure modes and ensure user-initiated aborts or benign conditions exit with 0 where appropriate.

* Use exit 105 for unsupported PVE versions

Standardize error handling by replacing generic exit 1 with exit 105 in pve_check() across multiple VM template scripts to indicate unsupported Proxmox VE versions. Also add API exit code 226 message for "Proxmox: VM disk import or post-creation setup failed" in misc/api.func. Affected files include misc/api.func and various vm/*-vm.sh scripts.

* Use specific exit codes in VM scripts

Replace generic exit 1 with distinct exit codes across vm/*.sh to make failures more actionable for callers. Changes include: use 226 for missing imported-disk references, 237 for pv installation failures, 115 for download/extract/ISO-related failures, 214 for insufficient disk space during FreeBSD decompression, and 119 for missing storage detection. Updated scripts: archlinux-vm.sh, docker-vm.sh, haos-vm.sh, openwrt-vm.sh, opnsense-vm.sh, truenas-vm.sh, umbrel-os-vm.sh.
2026-03-02 10:55:20 +01:00
CanbiZ (MickLesk)
9f15ca6242 Simplify lxc-attach logging and terminal handling
Remove host-side tee capture of lxc-attach output and PIPESTATUS handling; lxc-attach is now invoked directly and the exit code is taken from $?. Simplify install log retrieval by pulling /root/.install-<SESSION_ID>.log directly and removing the fallback that used the host-captured terminal log, related temp-file size checks, and timeout logic. Remove terminal-state restores and input-draining (stty/dd) and stop redirecting reads from /dev/tty so interactive reads use standard input; similar simplifications applied to the retry flow. Also remove cleanup of the discarded capture log. These changes reduce complexity and terminal manipulation, at the cost of losing the previous terminal-capture fallback for installs that failed to produce a container-side log.
2026-03-02 10:46:25 +01:00
CanbiZ (MickLesk)
750b904abc Flush terminal input and make repo cache global
Restore and sanitize terminal state before prompting by draining stale input from /dev/tty (dd iflag=nonblock) and adding a short sleep, then perform timed reads from /dev/tty in misc/build.func and misc/error_handler.func. Also make _REPO_CACHE a global associative array (declare -gA) with fallbacks in misc/tools.func so the cache survives when tools.func is sourced inside a function scope.
2026-03-02 10:40:17 +01:00
CanbiZ (MickLesk)
96b5411d1d Use PG_VERSION var; default to vendor repos
Pass PG_VERSION from the Mealie installer (replace POSTGRES_VERSION with PG_VERSION) and update misc/tools.func to prefer vendor package repos by default. Adjusted comments/examples for setup_mysql and setup_postgresql to reflect the new default behavior, and changed the local default for USE_MYSQL_REPO to true. These changes align variable naming in the installer and clarify that official MySQL/PGDG repositories are used unless explicitly disabled.
2026-03-02 10:35:30 +01:00
CanbiZ (MickLesk)
a3404102ce Update tools.func 2026-03-02 10:29:04 +01:00
CanbiZ (MickLesk)
374c4492d9 Read prompts from a fresh /dev/tty to avoid tty corruption
Replace pre-opened _RECOVERY_TTY handling with direct reads from /dev/tty in misc/build.func and misc/error_handler.func. The change opens /dev/tty at prompt time (with stty sane) so the prompt reads aren't affected by tty state corruption from lxc-attach|tee, simplifies the read logic by using a local response variable with a timeout, and removes the pre-open/close bookkeeping for _RECOVERY_TTY.
2026-03-02 10:25:19 +01:00
CanbiZ (MickLesk)
3cfe86512d Fix read failures in install scripts and recovery menu
Two critical bugs fixed:

1. Install scripts (80+) using 'read' for interactive prompts all fail because
   lxc-attach stdin was redirected from /dev/null. Change to /dev/tty so install
   scripts like immich, elementsynapse, etc. can prompt the user interactively.

2. Recovery menu read gets 'Input/output error' from /dev/tty after the
   lxc-attach|tee pipeline corrupts the terminal state. Pre-open a separate
   file descriptor to /dev/tty BEFORE the pipeline starts. This fd survives
   any tty corruption and is used as fallback for the recovery menu read.
   Fixes the 'command not found' issue where user input falls through to the
   parent shell.

Both build.func (main install + APT retry) and error_handler.func (fallback
cleanup prompt) are updated with the same pattern.
2026-03-02 10:05:55 +01:00
community-scripts-pr-app[bot]
47e3e415b9 Update .app files (#12464)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-02 09:41:21 +01:00
community-scripts-pr-app[bot]
3373533725 Update CHANGELOG.md (#12466)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 08:36:59 +00:00
community-scripts-pr-app[bot]
62c7c329d7 Update CHANGELOG.md (#12465)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 08:36:43 +00:00
community-scripts-pr-app[bot]
da04899558 Update date in json (#12463)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-02 08:36:34 +00:00
push-app-to-main[bot]
e49f09b5ec Profilarr (#12441) 2026-03-02 09:36:16 +01:00
CanbiZ (MickLesk)
53efcdc9df Redirect lxc-attach stdin; restore terminal
Prevent the lxc-attach pipeline from consuming the host's stdin by redirecting its stdin from /dev/null, keeping /dev/tty available for the recovery menu after SIGINT or failures (avoids "read: read error: Input/output error"). Also restore terminal state after the pipeline by running `stty sane` (errors ignored). Applied these changes to both installation invocation sites in misc/build.func.
2026-03-02 09:29:55 +01:00
CanbiZ (MickLesk)
d9e53d5a16 Remove non-TTY static spinner fallback
Delete the stderr TTY check and the static spinner printf/early return in msg_info. The function now always calls color_spinner and starts the animated spinner in the background, removing the special-case for piped/non-TTY environments and simplifying terminal handling.
2026-03-02 09:26:24 +01:00
CanbiZ (MickLesk)
8699013eef Merge branch 'main' of https://github.com/community-scripts/ProxmoxVE 2026-03-02 09:16:57 +01:00
CanbiZ (MickLesk)
e3af8ad287 Only strip v for digit tags; sanitize version
Improve GitHub release tag handling: only remove a leading 'v' when it's followed by a digit (avoids mangling tags like "version/..."), and sanitize the derived version string for filenames by replacing '/' with '-'. Use the sanitized version when constructing the downloaded tarball filename to prevent invalid or unexpected paths.
2026-03-02 09:16:25 +01:00
CanbiZ (MickLesk)
f2970522a9 Handle non-TTY output; simplify verbosity check
Detect non-TTY stderr in msg_info() and print a static progress indicator instead of launching the background spinner (which is unreliable when output is piped). Remove the non-TTY check from is_verbose_mode() and add comments clarifying that non-TTY behavior is handled in msg_info(). Apply the same verbosity simplification to vm-core.func. This keeps spinner visuals working when passed through pipes while avoiding backgrounding issues.
2026-03-02 09:08:55 +01:00
community-scripts-pr-app[bot]
e1a45c4831 Update CHANGELOG.md (#12462)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 08:02:17 +00:00
CanbiZ (MickLesk)
d258ff476f fix(frontend): improve detail view badges, addon texts, and HTML title (#12461) 2026-03-02 09:01:48 +01:00
community-scripts-pr-app[bot]
a0ea2263a6 Update .app files (#12459)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-03-02 08:45:36 +01:00
community-scripts-pr-app[bot]
d29e4cf4a2 Update CHANGELOG.md (#12460)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 07:45:21 +00:00
community-scripts-pr-app[bot]
6095defed4 Update CHANGELOG.md (#12458)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 07:45:13 +00:00
CanbiZ (MickLesk)
edd88d33d5 tools.func: Improve stability with retry logic, caching, and debug mode (#10351)
* refactor(tools.func): use distro packages by default for stability

- fetch_and_deploy_gh_release: add validation for empty app names
  - Derives app name from repo if not provided
  - Prevents '/root/.: Is a directory' error (fixes #10342)

- setup_hwaccel: fix Intel driver app names for fetch_and_deploy_gh_release
  - Add proper app names: intel-igc-core, intel-igc-opencl, libigdgmm12, intel-opencl-icd

- setup_mariadb: use distro packages by default
  - Default: apt packages (default-mysql-server, mariadb-server)
  - Optional: USE_MARIADB_REPO=true for official MariaDB repo
  - Fixes GPG key/mirror availability issues

- setup_mysql: use distro packages by default
  - Default: apt packages (default-mysql-server, mysql-server)
  - Optional: USE_MYSQL_REPO=true for official MySQL repo
  - Keeps Debian Trixie 8.4 LTS handling when using official repo

- setup_postgresql: use distro packages by default
  - Default: apt packages (postgresql, postgresql-client)
  - Optional: USE_PGDG_REPO=true for official PGDG repo

- setup_docker: use distro packages by default
  - Default: docker.io package
  - Optional: USE_DOCKER_REPO=true for official Docker repo
  - Maintains Portainer support in both modes

This refactoring prioritizes stability by using well-tested distro
packages while maintaining the option to use official repos for
specific version requirements.

* feat(tools.func): add retry logic and debug mode for stability

New helper functions:
- curl_with_retry: Robust curl wrapper with retry logic (3 attempts)
- curl_api_with_retry: API calls with HTTP status handling
- download_gpg_key: GPG key download with retry and dearmor support
- debug_log: Conditional debug output when TOOLS_DEBUG=true

Replaced critical curl calls:
- MongoDB GPG key download
- NodeSource GPG key download
- PostgreSQL GPG key download
- PHP (Sury) keyring download
- MySQL GPG key download
- setup_deb822_repo GPG import

Benefits:
- Automatic retry on transient network failures
- Configurable timeouts (CURL_TIMEOUT, CURL_CONNECT_TO)
- Debug mode for troubleshooting (TOOLS_DEBUG=true)
- Consistent error handling across all GPG key imports

* feat(tools.func): extend retry logic to all major downloads

Added curl_with_retry to all critical download operations:
- Adminer download
- Composer installer
- FFmpeg (binary and source)
- Go tarball
- Ghostscript source
- ImageMagick source
- rbenv and ruby-build
- uv (astral-sh)
- yq binary
- Go version check

Extended timeouts for large downloads:
- CURL_TIMEOUT=300 for FFmpeg, Go (large tarballs)
- CURL_TIMEOUT=180 for Ghostscript, ImageMagick

Remaining without retry (intentional):
- download_with_progress (specialized function)
- Rustup installer (piped to shell)
- Portainer version check (non-critical)

Total curl_with_retry/download_gpg_key usage: 27 locations

* typo

* Fix removed features in refactor branch

- Add libmfx-gen1.2 back for Intel Quick Sync Video encoding (Debian 12+13)
- Restore tmpfiles.d configuration for MariaDB /run/mysqld persistence
- Fix MariaDB fallback version from 11.4 to 12.2 (latest GA version)

These changes were incorrectly removed in the refactor commits.

* Optimize tools.func: fix typos, duplicate debug_log, Node.js version, PG backup, Intel VPL

* Optimize tools.func: intelligent fallbacks, retry logic, caching, DNS pre-check

- curl_with_retry: DNS pre-check + exponential backoff
- download_gpg_key: Auto-detect key format, validation
- ensure_dependencies: Batch dpkg-query check, individual fallback
- install_packages_with_retry: Progressive recovery (dpkg fix, broken deps, individual packages)
- verify_repo_available: Caching with TTL to avoid repeated HTTP requests
- get_fallback_suite: Dynamic HTTP availability check cascade
- ensure_apt_working: APT lock handling, progressive recovery
- safe_service_restart: Wait-for-ready with configurable timeout, retry logic
- get_latest_github_release: Fallback to tags API, prerelease support, rate limit handling

* foirmatting

* tools.func: Smarter parallel jobs calculation with load awareness

- get_parallel_jobs: Add memory-based limiting (1.5GB/job), load awareness,
  and container detection for conservative limits
- get_default_php_version: Add future versions (Debian 14, Ubuntu 26.04),
  update defaults to 8.3
- get_default_python_version: Add future versions, update defaults to 3.12

* fix: whitespace cleanup and indentation fix in tools.func
2026-03-02 08:44:59 +01:00
CanbiZ (MickLesk)
fd67210906 Migrate: DokPloy, Komodo, Coolify, Dockge, Runtipi to Addons (#12275)
* feat: add Docker-based tool addons for dockge, komodo, dokploy, npmplus

Create addon scripts following the arcane.sh pattern for Docker-based
tools that can be installed on any existing Docker LXC:

- dockge: Docker Compose stack manager (port 5001)
- komodo: Build/deployment system with MongoDB/FerretDB (port 9120)
- dokploy: PaaS via external installer with Redis (port 3000)
- npmplus: Nginx Proxy Manager Plus via Compose (port 81)

Each addon includes:
- Docker availability check
- Install with full configuration
- Update via docker compose pull
- Uninstall with container cleanup
- ASCII header files

Original ct/ and install/ scripts are preserved for now.

* refactor: convert Docker tools to addons, remove old scripts

Convert dockge, komodo, dokploy, coolify from standalone ct/install
scripts to addon pattern (like arcane.sh).

Added:
- tools/addon/dockge.sh (port 5001)
- tools/addon/komodo.sh (port 9120, MongoDB/FerretDB choice)
- tools/addon/dokploy.sh (port 3000, external installer)
- tools/addon/coolify.sh (port 8000, external installer)
- tools/headers/ for all 4

Removed:
- ct/dockge.sh, ct/komodo.sh, ct/alpine-komodo.sh, ct/dokploy.sh, ct/coolify.sh
- install/dockge-install.sh, install/komodo-install.sh, install/alpine-komodo-install.sh
- install/dokploy-install.sh, install/coolify-install.sh
- frontend/public/json/ for dockge, komodo, dokploy, coolify
- tools/addon/npmplus.sh (not an addon candidate)

These tools are Docker-only and fit the addon pattern: they require
an existing Docker LXC and manage containers via docker compose.

* feat: add addon JSON configs for dockge, komodo, dokploy, coolify

Recreate JSON configs with type=addon, script paths pointing to
tools/addon/*.sh, null resources (addon runs on existing Docker LXC),
and update instructions in notes.

* feat: add Runtipi addon + upgrade all addons with Proxmox host check, optional Docker install, Alpine support

- New: tools/addon/runtipi.sh with full Alpine support (gcompat for musl)
- New: tools/headers/runtipi ASCII header
- Updated: runtipi.json to addon type with null resources
- Removed: ct/runtipi.sh, install/runtipi-install.sh (migrated to addon)
- All addons (dockge, komodo, dokploy, coolify, runtipi) now have:
  - check_proxmox_host(): warns when running on PVE host, default N
  - check_or_install_docker(): optional Docker install (Debian+Alpine)
  - Alpine-aware curl bootstrap and dependency installation

* readd ct, update information

* Create runtipi.sh

* refactor: remove inline header_info from addons, use core.func get_header()

- get_header() in core.func now maps APP_TYPE=addon to tools/headers/ path
- Removed 5 duplicate ASCII art header_info functions from addon scripts
- Addons now use the shared header_info() from core.func + tools/headers/ files

* chore(tools): add Github source links to dockge, komodo, dokploy, coolify, runtipi addons

* fix(runtipi): drop Alpine support; add OS compat notes to docker addon JSONs
2026-03-02 08:44:49 +01:00
community-scripts-pr-app[bot]
393e9bd868 chore: update github-versions.json (#12456)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 06:20:24 +00:00
community-scripts-pr-app[bot]
339863366c Update CHANGELOG.md (#12454)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 00:21:00 +00:00
community-scripts-pr-app[bot]
d8db023931 chore: update github-versions.json (#12453)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 00:20:37 +00:00
community-scripts-pr-app[bot]
71ccc82853 Update CHANGELOG.md (#12450)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-01 21:10:23 +00:00
Tom Frenzel
4d837d82d8 Sparkyfitness: use pnpm (#12445)
* fix(sparkyfitness): use pnpm

* chore: use pinned pnpm

* fix: move node and pnpm update
2026-03-01 22:09:57 +01:00
community-scripts-pr-app[bot]
59792ad8b9 Update CHANGELOG.md (#12449)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-01 19:42:17 +00:00
Slaviša Arežina
020796d411 Fix install (#12447) 2026-03-01 20:41:55 +01:00
community-scripts-pr-app[bot]
cc7461d959 chore: update github-versions.json (#12448)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-01 18:07:16 +00:00
community-scripts-pr-app[bot]
0fc12576c0 chore: update github-versions.json (#12443)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-01 12:08:03 +00:00
122 changed files with 3302 additions and 1128 deletions

155
.github/workflows/push-json-to-pocketbase.yml generated vendored Normal file
View File

@@ -0,0 +1,155 @@
name: Push JSON changes to PocketBase
on:
push:
branches:
- main
paths:
- "frontend/public/json/**"
jobs:
push-json:
runs-on: self-hosted
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed JSON files with slug
id: changed
run: |
changed=$(git diff --name-only "${{ github.event.before }}" "${{ github.event.after }}" -- frontend/public/json/ | grep '\.json$' || true)
with_slug=""
for f in $changed; do
[[ -f "$f" ]] || continue
jq -e '.slug' "$f" >/dev/null 2>&1 && with_slug="$with_slug $f"
done
with_slug=$(echo $with_slug | xargs -n1)
if [[ -z "$with_slug" ]]; then
echo "No app JSON files changed (or no files with slug)."
echo "count=0" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "$with_slug" > changed_app_jsons.txt
echo "count=$(echo "$with_slug" | wc -w)" >> "$GITHUB_OUTPUT"
- name: Push to PocketBase
if: steps.changed.outputs.count != '0'
env:
POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
run: |
node << 'ENDSCRIPT'
(async function() {
const fs = require('fs');
const https = require('https');
const http = require('http');
const url = require('url');
function request(fullUrl, opts) {
return new Promise(function(resolve, reject) {
const u = url.parse(fullUrl);
const isHttps = u.protocol === 'https:';
const body = opts.body;
const options = {
hostname: u.hostname,
port: u.port || (isHttps ? 443 : 80),
path: u.path,
method: opts.method || 'GET',
headers: opts.headers || {}
};
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
const lib = isHttps ? https : http;
const req = lib.request(options, function(res) {
let data = '';
res.on('data', function(chunk) { data += chunk; });
res.on('end', function() {
resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
});
});
req.on('error', reject);
if (body) req.write(body);
req.end();
});
}
const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
const coll = process.env.POCKETBASE_COLLECTION;
const files = fs.readFileSync('changed_app_jsons.txt', 'utf8').trim().split(/\s+/).filter(Boolean);
const authBody = JSON.stringify({
identity: process.env.POCKETBASE_ADMIN_EMAIL,
password: process.env.POCKETBASE_ADMIN_PASSWORD
});
let authRes = await request(apiBase + '/admins/auth-with-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: authBody
});
if (!authRes.ok && authRes.statusCode === 404) {
authRes = await request(raw + '/admins/auth-with-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: authBody
});
}
if (!authRes.ok) throw new Error('Auth failed (check POCKETBASE_URL): ' + authRes.body);
const token = JSON.parse(authRes.body).token;
const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';
for (const file of files) {
if (!fs.existsSync(file)) continue;
const data = JSON.parse(fs.readFileSync(file, 'utf8'));
if (!data.slug) { console.log('Skipping', file, '(no slug)'); continue; }
var payload = {
name: data.name,
slug: data.slug,
script_created: data.date_created || data.script_created,
script_updated: data.date_created || data.script_updated,
updateable: data.updateable,
privileged: data.privileged,
port: data.interface_port != null ? data.interface_port : data.port,
documentation: data.documentation,
website: data.website,
logo: data.logo,
description: data.description,
config_path: data.config_path,
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd,
categories: data.categories,
install_methods: data.install_methods,
notes: data.notes,
type: data.type,
is_dev: false
};
if (data.version !== undefined) payload.version = data.version;
if (data.changelog !== undefined) payload.changelog = data.changelog;
if (data.screenshots !== undefined) payload.screenshots = data.screenshots;
const filter = "(slug='" + data.slug + "')";
const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
headers: { 'Authorization': token }
});
const list = JSON.parse(listRes.body);
const existingId = list.items && list.items[0] && list.items[0].id;
if (existingId) {
console.log('Updating', file, '(slug=' + data.slug + ')');
const r = await request(recordsUrl + '/' + existingId, {
method: 'PATCH',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r.ok) throw new Error('PATCH failed: ' + r.body);
} else {
console.log('Creating', file, '(slug=' + data.slug + ')');
const r = await request(recordsUrl, {
method: 'POST',
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!r.ok) throw new Error('POST failed: ' + r.body);
}
}
console.log('Done.');
})().catch(e => { console.error(e); process.exit(1); });
ENDSCRIPT
shell: bash

View File

@@ -410,8 +410,53 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-03-02
### 🆕 New Scripts
- Profilarr ([#12441](https://github.com/community-scripts/ProxmoxVE/pull/12441))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Tracearr: prepare for imminent v1.4.19 release [@durzo](https://github.com/durzo) ([#12413](https://github.com/community-scripts/ProxmoxVE/pull/12413))
- #### ✨ New Features
- Frigate: Bump to v0.17 [@MickLesk](https://github.com/MickLesk) ([#12474](https://github.com/community-scripts/ProxmoxVE/pull/12474))
- #### 💥 Breaking Changes
- Migrate: DokPloy, Komodo, Coolify, Dockge, Runtipi to Addons [@MickLesk](https://github.com/MickLesk) ([#12275](https://github.com/community-scripts/ProxmoxVE/pull/12275))
- #### 🔧 Refactor
- ref: replace generic exit 1 with specific exit codes in ct & install [@MickLesk](https://github.com/MickLesk) ([#12475](https://github.com/community-scripts/ProxmoxVE/pull/12475))
### 💾 Core
- #### ✨ New Features
- tools.func: Improve stability with retry logic, caching, and debug mode [@MickLesk](https://github.com/MickLesk) ([#10351](https://github.com/community-scripts/ProxmoxVE/pull/10351))
- #### 🔧 Refactor
- core: standardize exit codes and add mappings [@MickLesk](https://github.com/MickLesk) ([#12467](https://github.com/community-scripts/ProxmoxVE/pull/12467))
### 🌐 Website
- frontend: improve detail view badges, addon texts, and HTML title [@MickLesk](https://github.com/MickLesk) ([#12461](https://github.com/community-scripts/ProxmoxVE/pull/12461))
## 2026-03-01
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Sparkyfitness: use pnpm [@tomfrenzel](https://github.com/tomfrenzel) ([#12445](https://github.com/community-scripts/ProxmoxVE/pull/12445))
- OpenArchiver: Fix installation [@tremor021](https://github.com/tremor021) ([#12447](https://github.com/community-scripts/ProxmoxVE/pull/12447))
## 2026-02-28
### 🚀 Updated Scripts

View File

@@ -19,44 +19,46 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh"
function update_script() {
[[ -d /opt/komodo ]] || {
if [[ ! -d /opt/komodo ]]; then
msg_error "No ${APP} Installation Found!"
exit
}
msg_info "Updating ${APP}"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit
fi
COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
if [[ "$COMPOSE_BASENAME" == "sqlite.compose.yaml" || "$COMPOSE_BASENAME" == "postgres.compose.yaml" ]]; then
msg_error "❌ Detected outdated Komodo setup using SQLite or PostgreSQL (FerretDB v1)."
echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}"
echo -e "${YW}Please follow the migration guide:${CL}"
echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n"
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_komodo${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 252
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated ${APP}"
exit
fi
BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
exit
}
GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
mv "$BACKUP_FILE" "$COMPOSE_FILE"
exit
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated Alpine-Komodo"
msg_ok "Updated successfully!"
exit 0
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_komodo 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit
}
start

View File

@@ -19,6 +19,8 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh"
function update_script() {
header_info
check_container_storage
@@ -29,10 +31,31 @@ function update_script() {
exit
fi
msg_info "Updating Coolify"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Updated Coolify"
msg_ok "Updated successfully!"
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_coolify${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_coolify 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
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
# Author: tteck (tteckster)
# Author: tteck (tteckster) | Migration: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dockge.kuma.pet/
@@ -19,26 +19,45 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh"
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/dockge ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating base system"
$STD apt update
$STD apt upgrade -y
msg_ok "Base system updated"
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_dockge${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
cd /opt/dockge
$STD docker compose pull
$STD docker compose up -d
msg_ok "Updated ${APP}"
exit
fi
msg_info "Updating Dockge"
cd /opt/dockge
$STD docker compose pull
$STD docker compose up -d
msg_ok "Updated Dockge"
msg_ok "Updated successfully!"
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_dockge 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit
}

View File

@@ -19,6 +19,8 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh"
function update_script() {
header_info
check_container_storage
@@ -29,10 +31,31 @@ function update_script() {
exit
fi
msg_info "Updating Dokploy"
curl -sSL https://dokploy.com/install.sh | $STD bash -s update
msg_ok "Updated Dokploy"
msg_ok "Updated successfully!"
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_dokploy${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
curl -sSL https://dokploy.com/install.sh | $STD bash -s update
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_dokploy 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit
}

View File

@@ -26,7 +26,7 @@ function update_script() {
if [[ ! -d /opt/endurain ]]; then
msg_error "No ${APP} installation found!"
exit 1
exit 233
fi
if check_for_gh_release "endurain" "endurain-project/endurain"; then
msg_info "Stopping Service"

View File

@@ -25,7 +25,7 @@ function update_script() {
check_container_resources
if ! command -v evcc >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit 1
exit 233
fi
if [[ -f /etc/apt/sources.list.d/evcc-stable.list ]]; then

View File

@@ -26,7 +26,7 @@ function update_script() {
if ! dpkg -s grafana >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit 1
exit 233
fi
if [[ -f /etc/apt/sources.list.d/grafana.list ]] || [[ ! -f /etc/apt/sources.list.d/grafana.sources ]]; then

6
ct/headers/profilarr Normal file
View File

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

View File

@@ -26,7 +26,7 @@ function update_script() {
if [[ ! -f /etc/itsm-ng/config_db.php ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
exit 233
fi
setup_mariadb

View File

@@ -45,7 +45,7 @@ function update_script() {
if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then
msg_error "Unable to detect latest Kasm release URL."
exit 1
exit 250
fi
msg_info "Checked for new version"

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 community-scripts ORG
# Author: MickLesk
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do/
@@ -19,49 +19,49 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh"
function update_script() {
header_info
check_container_storage
check_container_resources
[[ -d /opt/komodo ]] || {
if [[ ! -d /opt/komodo ]]; then
msg_error "No ${APP} Installation Found!"
exit 1
}
msg_info "Updating Komodo"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 1
fi
COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
if [[ "$COMPOSE_BASENAME" == "sqlite.compose.yaml" || "$COMPOSE_BASENAME" == "postgres.compose.yaml" ]]; then
msg_error "❌ Detected outdated Komodo setup using SQLite or PostgreSQL (FerretDB v1)."
echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}"
echo -e "${YW}Please follow the migration guide:${CL}"
echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n"
exit 1
exit
fi
BACKUP_FILE="/opt/komodo/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
exit 1
}
GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
mv "$BACKUP_FILE" "$COMPOSE_FILE"
exit 1
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_komodo${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
COMPOSE_FILE=$(find /opt/komodo -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "$COMPOSE_FILE" ]]; then
msg_error "No valid compose file found in /opt/komodo!"
exit 252
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated ${APP}"
exit
fi
if ! grep -qxF 'COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' /opt/komodo/compose.env; then
sed -i '/^COMPOSE_KOMODO_IMAGE_TAG=latest$/a COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' /opt/komodo/compose.env
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Updated Komodo"
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_komodo 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit
}

View File

@@ -26,7 +26,7 @@ function update_script() {
if ! dpkg -s loki >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit 1
exit 233
fi
CHOICE=$(msg_menu "Loki Update Options" \

View File

@@ -44,7 +44,7 @@ function update_script() {
echo -e "${TAB}${GATEWAY}${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/9223${CL}"
echo -e ""
msg_custom "⚠️" "Update aborted. Please migrate your data first."
exit 1
exit 253
fi
fi

85
ct/profilarr.sh Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Dictionarry-Hub/profilarr
APP="Profilarr"
var_tags="${var_tags:-arr;radarr;sonarr;config}"
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/profilarr ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "profilarr" "Dictionarry-Hub/profilarr"; then
msg_info "Stopping Service"
systemctl stop profilarr
msg_ok "Stopped Service"
msg_info "Backing up Data"
if [[ -d /config ]]; then
cp -r /config /opt/profilarr_config_backup
fi
msg_ok "Backed up Data"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "profilarr" "Dictionarry-Hub/profilarr" "tarball"
msg_info "Installing Python Dependencies"
cd /opt/profilarr/backend
$STD uv venv /opt/profilarr/backend/.venv
sed 's/==/>=/g' requirements.txt >requirements-relaxed.txt
$STD uv pip install --python /opt/profilarr/backend/.venv/bin/python -r requirements-relaxed.txt
rm -f requirements-relaxed.txt
msg_ok "Installed Python Dependencies"
msg_info "Building Frontend"
if [[ -d /opt/profilarr/frontend ]]; then
cd /opt/profilarr/frontend
$STD npm install
$STD npm run build
cp -r dist /opt/profilarr/backend/app/static
fi
msg_ok "Built Frontend"
msg_info "Restoring Data"
if [[ -d /opt/profilarr_config_backup ]]; then
mkdir -p /config
cp -r /opt/profilarr_config_backup/. /config/
rm -rf /opt/profilarr_config_backup
fi
msg_ok "Restored Data"
msg_info "Starting Service"
systemctl start profilarr
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}:6868${CL}"

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)
# Author: tteck (tteckster) | Migration: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://runtipi.io/
@@ -19,16 +19,43 @@ variables
color
catch_errors
ADDON_SCRIPT="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh"
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/runtipi ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
cd /opt/runtipi && ./runtipi-cli update latest
msg_ok "Updated successfully!"
msg_warn "⚠️ ${APP} has been migrated to an addon script."
echo ""
msg_info "This is a one-time migration. After this, you can update ${APP} anytime with:"
echo -e "${TAB}${TAB}${GN}update_runtipi${CL} or ${GN}bash <(curl -fsSL ${ADDON_SCRIPT})${CL}"
echo ""
read -r -p "${TAB}Migrate update function now? [y/N]: " CONFIRM
if [[ ! "${CONFIRM,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Migration skipped. The old update will continue to work for now."
msg_info "Updating ${APP} (legacy)"
cd /opt/runtipi && ./runtipi-cli update latest
msg_ok "Updated ${APP}"
exit
fi
msg_info "Migrating update function"
cat <<'MIGRATION_EOF' >/usr/bin/update
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh)"
MIGRATION_EOF
chmod +x /usr/bin/update
ln -sf /usr/bin/update /usr/bin/update_runtipi 2>/dev/null || true
msg_ok "Migration complete"
msg_info "Running addon update"
type=update bash <(curl -fsSL "${ADDON_SCRIPT}")
exit
}

View File

@@ -29,8 +29,6 @@ function update_script() {
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
@@ -48,6 +46,9 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness" "tarball"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1]' /opt/sparkyfitness/package.json)"
NODE_VERSION="25" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
msg_info "Updating Sparky Fitness Backend"
cd /opt/sparkyfitness/SparkyFitnessServer
$STD npm install
@@ -55,8 +56,8 @@ function update_script() {
msg_info "Updating Sparky Fitness Frontend (Patience)"
cd /opt/sparkyfitness/SparkyFitnessFrontend
$STD npm install
$STD npm run build
$STD pnpm install
$STD pnpm run build
cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/
msg_ok "Updated Sparky Fitness Frontend"

View File

@@ -75,10 +75,31 @@ if [ -f \$pg_config_file ]; then
fi
fi
systemctl restart postgresql
sudo -u postgres psql -c "ALTER USER tracearr WITH SUPERUSER;"
EOF
chmod +x /data/tracearr/prestart.sh
msg_ok "Updated prestart script"
# check if tailscale is installed
if command -v tailscale >/dev/null 2>&1; then
# Tracearr runs tailscaled in user mode, disable the service.
$STD systemctl disable --now tailscaled
$STD systemctl stop tailscaled
msg_ok "Tailscale already installed"
else
msg_info "Installing tailscale"
setup_deb822_repo \
"tailscale" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/$(get_os_info codename).noarmor.gpg" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/" \
"$(get_os_info codename)"
$STD apt install -y tailscale
# Tracearr runs tailscaled in user mode, disable the service.
$STD systemctl disable --now tailscaled
$STD systemctl stop tailscaled
msg_ok "Installed tailscale"
fi
if check_for_gh_release "tracearr" "connorgallopo/Tracearr"; then
msg_info "Stopping Services"
systemctl stop tracearr postgresql redis
@@ -122,6 +143,8 @@ EOF
sed -i "s/^APP_VERSION=.*/APP_VERSION=$(cat /root/.tracearr)/" /data/tracearr/.env
chmod 600 /data/tracearr/.env
chown -R tracearr:tracearr /data/tracearr
mkdir -p /data/backup
chown -R tracearr:tracearr /data/backup
msg_ok "Configured Tracearr"
msg_info "Starting services"

View File

@@ -34,14 +34,14 @@ function update_script() {
msg_warn "This requires MANUAL config changes in /etc/vikunja/config.yml."
msg_warn "See: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes"
read -rp "Continue with update? (y to proceed): " -t 30 CONFIRM1 || exit 1
read -rp "Continue with update? (y to proceed): " -t 30 CONFIRM1 || exit 254
[[ "$CONFIRM1" =~ ^[yY]$ ]] || exit 0
echo
msg_warn "Vikunja may not start after the update until you manually adjust the config."
msg_warn "Details: https://vikunja.io/changelog/whats-new-in-vikunja-1.0.0/#config-changes"
read -rp "Acknowledge and continue? (y): " -t 30 CONFIRM2 || exit 1
read -rp "Acknowledge and continue? (y): " -t 30 CONFIRM2 || exit 254
[[ "$CONFIRM2" =~ ^[yY]$ ]] || exit 0
fi

View File

@@ -13,7 +13,7 @@
"website": "https://2fauth.app/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/2fauth.webp",
"config_path": "cat /opt/2fauth/.env",
"description": "2FAuth is a web based self-hosted alternative to One Time Passcode (OTP) generators like Google Authenticator, designed for both mobile and desktop. It aims to ease you perform your 2FA authentication steps whatever the device you handle, with a clean and suitable interface.",
"description": "2FAuth is a web based self-hosted alternative to One Time Passcode (OTP) generators like Google Authenticator, designed for both mobile and desktop. It aims to ease you perform your 2FA authentication steps whatever the device you handle, with a clean and suitable interface. - Workflow - Test",
"install_methods": [
{
"type": "default",

View File

@@ -1,52 +1,56 @@
{
"name": "Coolify",
"slug": "coolify",
"categories": [
3
],
"date_created": "2025-12-09",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://coolify.io/docs",
"config_path": "/data/coolify",
"website": "https://coolify.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/coolify.webp",
"description": "Coolify is an open-source & self-hostable alternative to Heroku, Netlify, and Vercel. It helps you manage your servers, applications, and databases on your own hardware with Docker. Deploy any application from Git repositories, Docker images, or use pre-built templates.",
"install_methods": [
{
"type": "default",
"script": "ct/coolify.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 30,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Coolify",
"slug": "coolify",
"categories": [
3
],
"date_created": "2025-12-09",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://coolify.io/docs",
"website": "https://coolify.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/coolify.webp",
"config_path": "/data/coolify",
"description": "Coolify is an open-source & self-hostable alternative to Heroku, Netlify, and Vercel. It helps you manage your servers, applications, and databases on your own hardware with Docker. Deploy any application from Git repositories, Docker images, or use pre-built templates.",
"install_methods": [
{
"type": "default",
"script": "tools/addon/coolify.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
"notes": [
{
"text": "Initial setup will be done via the web interface on first access.",
"type": "info"
},
{
"text": "Coolify has built-in auto-updates. You can configure update frequency in Settings.",
"type": "info"
},
{
"text": "Coolify requires SSH access to manage deployments. SSH is enabled automatically.",
"type": "info"
},
{
"text": "This container uses Docker-in-Docker (nesting) for application deployments.",
"type": "warning"
}
]
{
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)",
"type": "info"
},
{
"text": "Initial setup will be done via the web interface on first access.",
"type": "info"
},
{
"text": "Coolify has built-in auto-updates. You can configure update frequency in Settings.",
"type": "info"
},
{
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coolify.sh)",
"type": "info"
}
]
}

View File

@@ -5,25 +5,25 @@
3
],
"date_created": "2024-05-02",
"type": "ct",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 5001,
"documentation": null,
"website": "https://github.com/louislam/dockge",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/dockge.webp",
"config_path": "",
"config_path": "/opt/dockge/compose.yaml",
"description": "Dockge is a fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager.",
"install_methods": [
{
"type": "default",
"script": "ct/dockge.sh",
"script": "tools/addon/dockge.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 18,
"os": "debian",
"version": "13"
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
@@ -33,12 +33,16 @@
},
"notes": [
{
"text": "Options to add Immich and/or Home Assistant",
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
{
"text": "If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"type": "warning"
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)",
"type": "info"
},
{
"text": "To update, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dockge.sh)",
"type": "info"
}
]
}

View File

@@ -1,48 +1,56 @@
{
"name": "Dokploy",
"slug": "dokploy",
"categories": [
3
],
"date_created": "2025-12-09",
"type": "ct",
"updateable": true,
"privileged": true,
"interface_port": 3000,
"documentation": "https://docs.dokploy.com/",
"config_path": "/etc/dokploy",
"website": "https://dokploy.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/dokploy.png",
"description": "Dokploy is a free, self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases. Built with Docker and Traefik, it offers features like automatic SSL, Docker Compose support, database backups, and a real-time monitoring dashboard.",
"install_methods": [
{
"type": "default",
"script": "ct/dokploy.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Dokploy",
"slug": "dokploy",
"categories": [
3
],
"date_created": "2025-12-09",
"type": "addon",
"updateable": true,
"privileged": true,
"interface_port": 3000,
"documentation": "https://docs.dokploy.com/",
"website": "https://dokploy.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/dokploy.png",
"config_path": "/etc/dokploy",
"description": "Dokploy is a free, self-hostable Platform as a Service (PaaS) that simplifies the deployment and management of applications and databases. Built with Docker and Traefik, it offers features like automatic SSL, Docker Compose support, database backups, and a real-time monitoring dashboard.",
"install_methods": [
{
"type": "default",
"script": "tools/addon/dokploy.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
"notes": [
{
"text": "Initial setup will be done via the web interface on first access.",
"type": "info"
},
{
"text": "Dokploy has built-in auto-updates via the web interface.",
"type": "info"
},
{
"text": "This container uses Docker-in-Docker (nesting) for application deployments.",
"type": "warning"
}
]
{
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)",
"type": "info"
},
{
"text": "Initial setup will be done via the web interface on first access.",
"type": "info"
},
{
"text": "Dokploy has built-in auto-updates via the web interface.",
"type": "info"
},
{
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/dokploy.sh)",
"type": "info"
}
]
}

View File

@@ -1,5 +1,5 @@
{
"generated": "2026-03-01T06:15:59Z",
"generated": "2026-03-02T13:48:26Z",
"versions": [
{
"slug": "2fauth",
@@ -116,9 +116,9 @@
{
"slug": "bentopdf",
"repo": "alam00000/bentopdf",
"version": "v2.3.3",
"version": "v2.4.0",
"pinned": false,
"date": "2026-02-27T08:40:05Z"
"date": "2026-03-01T14:25:43Z"
},
{
"slug": "beszel",
@@ -151,9 +151,9 @@
{
"slug": "booklore",
"repo": "booklore-app/BookLore",
"version": "v2.0.4",
"version": "v2.0.5",
"pinned": false,
"date": "2026-02-28T01:54:25Z"
"date": "2026-03-01T16:13:13Z"
},
{
"slug": "bookstack",
@@ -200,9 +200,9 @@
{
"slug": "cleanuparr",
"repo": "Cleanuparr/Cleanuparr",
"version": "v2.7.6",
"version": "v2.7.7",
"pinned": false,
"date": "2026-02-27T19:32:02Z"
"date": "2026-03-02T13:08:32Z"
},
{
"slug": "cloudreve",
@@ -270,9 +270,9 @@
{
"slug": "databasus",
"repo": "databasus/databasus",
"version": "v3.16.3",
"version": "v3.16.4",
"pinned": false,
"date": "2026-02-25T19:57:26Z"
"date": "2026-03-01T08:20:17Z"
},
{
"slug": "dawarich",
@@ -312,9 +312,9 @@
{
"slug": "domain-monitor",
"repo": "Hosteroid/domain-monitor",
"version": "v1.1.3",
"version": "v1.1.4",
"pinned": false,
"date": "2026-02-11T15:48:18Z"
"date": "2026-03-02T09:25:01Z"
},
{
"slug": "donetick",
@@ -424,9 +424,9 @@
{
"slug": "frigate",
"repo": "blakeblackshear/frigate",
"version": "v0.16.4",
"version": "v0.17.0",
"pinned": true,
"date": "2026-01-29T00:42:14Z"
"date": "2026-02-27T03:03:01Z"
},
{
"slug": "gatus",
@@ -438,9 +438,9 @@
{
"slug": "ghostfolio",
"repo": "ghostfolio/ghostfolio",
"version": "2.244.0",
"version": "2.245.0",
"pinned": false,
"date": "2026-02-28T09:51:45Z"
"date": "2026-03-01T09:09:57Z"
},
{
"slug": "gitea",
@@ -452,9 +452,9 @@
{
"slug": "gitea-mirror",
"repo": "RayLabsHQ/gitea-mirror",
"version": "v3.10.1",
"version": "v3.11.0",
"pinned": false,
"date": "2026-03-01T03:08:07Z"
"date": "2026-03-02T10:19:59Z"
},
{
"slug": "glance",
@@ -613,9 +613,9 @@
{
"slug": "jackett",
"repo": "Jackett/Jackett",
"version": "v0.24.1234",
"version": "v0.24.1247",
"pinned": false,
"date": "2026-03-01T05:55:44Z"
"date": "2026-03-02T05:56:37Z"
},
{
"slug": "jellystat",
@@ -634,9 +634,9 @@
{
"slug": "jotty",
"repo": "fccview/jotty",
"version": "1.20.0",
"version": "1.21.0",
"pinned": false,
"date": "2026-02-12T09:23:30Z"
"date": "2026-03-02T11:08:54Z"
},
{
"slug": "kapowarr",
@@ -669,16 +669,16 @@
{
"slug": "kima-hub",
"repo": "Chevron7Locked/kima-hub",
"version": "v1.6.0-rc.1",
"version": "v1.6.0",
"pinned": false,
"date": "2026-03-01T05:38:32Z"
"date": "2026-03-02T05:43:31Z"
},
{
"slug": "kimai",
"repo": "kimai/kimai",
"version": "2.50.0",
"version": "2.51.0",
"pinned": false,
"date": "2026-02-25T20:13:51Z"
"date": "2026-03-01T15:56:56Z"
},
{
"slug": "kitchenowl",
@@ -851,9 +851,9 @@
{
"slug": "mediamtx",
"repo": "bluenviron/mediamtx",
"version": "v1.16.2",
"version": "v1.16.3",
"pinned": false,
"date": "2026-02-22T17:31:41Z"
"date": "2026-03-01T15:49:12Z"
},
{
"slug": "meilisearch",
@@ -942,9 +942,9 @@
{
"slug": "nightscout",
"repo": "nightscout/cgm-remote-monitor",
"version": "15.0.4",
"version": "v15.0.5",
"pinned": false,
"date": "2026-02-28T17:07:02Z"
"date": "2026-03-01T21:22:37Z"
},
{
"slug": "nocodb",
@@ -956,9 +956,9 @@
{
"slug": "nodebb",
"repo": "NodeBB/NodeBB",
"version": "v4.9.0",
"version": "v4.9.1",
"pinned": false,
"date": "2026-02-27T19:20:51Z"
"date": "2026-03-01T20:52:43Z"
},
{
"slug": "nodecast-tv",
@@ -1124,9 +1124,9 @@
{
"slug": "planka",
"repo": "plankanban/planka",
"version": "v2.0.2",
"version": "v2.0.3",
"pinned": false,
"date": "2026-02-23T17:47:15Z"
"date": "2026-03-01T16:03:23Z"
},
{
"slug": "plant-it",
@@ -1156,6 +1156,13 @@
"pinned": false,
"date": "2025-11-12T07:10:14Z"
},
{
"slug": "profilarr",
"repo": "Dictionarry-Hub/profilarr",
"version": "v1.1.4",
"pinned": false,
"date": "2026-01-29T14:57:25Z"
},
{
"slug": "projectsend",
"repo": "projectsend/projectsend",
@@ -1215,9 +1222,9 @@
{
"slug": "pulse",
"repo": "rcourtman/Pulse",
"version": "v5.1.15",
"version": "v5.1.16",
"pinned": false,
"date": "2026-02-27T15:17:24Z"
"date": "2026-03-01T23:13:09Z"
},
{
"slug": "pve-scripts-local",
@@ -1278,9 +1285,9 @@
{
"slug": "rdtclient",
"repo": "rogerfar/rdt-client",
"version": "v2.0.124",
"version": "v2.0.125",
"pinned": false,
"date": "2026-02-24T03:18:03Z"
"date": "2026-03-01T18:29:10Z"
},
{
"slug": "reactive-resume",
@@ -1418,9 +1425,9 @@
{
"slug": "snowshare",
"repo": "TuroYT/snowshare",
"version": "v1.3.7",
"version": "v1.3.8",
"pinned": false,
"date": "2026-02-23T15:51:39Z"
"date": "2026-03-02T07:43:42Z"
},
{
"slug": "sonarr",
@@ -1579,9 +1586,9 @@
{
"slug": "trilium",
"repo": "TriliumNext/Trilium",
"version": "v0.101.3",
"version": "v0.102.0",
"pinned": false,
"date": "2026-01-08T18:05:22Z"
"date": "2026-03-01T20:37:40Z"
},
{
"slug": "trip",
@@ -1656,9 +1663,9 @@
{
"slug": "victoriametrics",
"repo": "VictoriaMetrics/VictoriaMetrics",
"version": "v1.136.0",
"version": "v1.137.0",
"pinned": false,
"date": "2026-02-16T13:17:50Z"
"date": "2026-03-02T10:09:29Z"
},
{
"slug": "vikunja",
@@ -1684,9 +1691,9 @@
{
"slug": "wanderer",
"repo": "meilisearch/meilisearch",
"version": "v1.36.0",
"version": "v1.37.0",
"pinned": false,
"date": "2026-02-23T08:13:32Z"
"date": "2026-03-02T09:16:36Z"
},
{
"slug": "warracker",
@@ -1789,9 +1796,9 @@
{
"slug": "zigbee2mqtt",
"repo": "Koenkk/zigbee2mqtt",
"version": "2.8.0",
"version": "2.9.1",
"pinned": false,
"date": "2026-02-01T19:27:25Z"
"date": "2026-03-02T11:16:46Z"
},
{
"slug": "zipline",
@@ -1803,9 +1810,9 @@
{
"slug": "zitadel",
"repo": "zitadel/zitadel",
"version": "v4.11.1",
"version": "v4.12.0",
"pinned": false,
"date": "2026-02-25T06:13:13Z"
"date": "2026-03-02T08:16:10Z"
},
{
"slug": "zoraxy",

View File

@@ -5,7 +5,7 @@
3
],
"date_created": "2025-01-01",
"type": "ct",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 9120,
@@ -17,24 +17,13 @@
"install_methods": [
{
"type": "default",
"script": "ct/komodo.sh",
"script": "tools/addon/komodo.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "debian",
"version": "13"
}
},
{
"type": "alpine",
"script": "ct/alpine-komodo.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 10,
"os": "alpine",
"version": "3.23"
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
@@ -44,7 +33,19 @@
},
"notes": [
{
"text": "For admin username and password type `cat ~/komodo.creds` inside LXC.",
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
{
"text": "Execute within an existing LXC console (Debian / Ubuntu / Alpine supported)",
"type": "info"
},
{
"text": "For admin username and password, run: cat ~/komodo.creds",
"type": "info"
},
{
"text": "To update, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/komodo.sh)",
"type": "info"
}
]

View File

@@ -0,0 +1,35 @@
{
"name": "Profilarr",
"slug": "profilarr",
"categories": [
14
],
"date_created": "2026-03-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 6868,
"documentation": "https://github.com/Dictionarry-Hub/profilarr#readme",
"website": "https://github.com/Dictionarry-Hub/profilarr",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/profilarr.webp",
"config_path": "/config",
"description": "Profilarr is a configuration management platform for Radarr and Sonarr that simplifies importing, syncing, and managing quality profiles, custom formats, and release profiles.",
"install_methods": [
{
"type": "default",
"script": "ct/profilarr.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -5,25 +5,25 @@
2
],
"date_created": "2024-05-02",
"type": "ct",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://runtipi.io/docs/introduction",
"website": "https://runtipi.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/runtipi.webp",
"config_path": "opt/runtipi/state/settings.json",
"config_path": "/opt/runtipi/state/settings.json",
"description": "Runtipi lets you install all your favorite self-hosted apps without the hassle of configuring and managing each service. One-click installs and updates for more than 180 popular apps.",
"install_methods": [
{
"type": "default",
"script": "ct/runtipi.sh",
"script": "tools/addon/runtipi.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "debian",
"version": "13"
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
@@ -32,9 +32,21 @@
"password": null
},
"notes": [
{
"text": "This is an addon script intended to be used on top of an existing Docker container.",
"type": "info"
},
{
"text": "Execute within an existing LXC console (Debian / Ubuntu only)",
"type": "info"
},
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
},
{
"text": "To update via CLI, run the addon script again and select Update, or use: bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/runtipi.sh)",
"type": "info"
}
]
}

View File

@@ -19,8 +19,9 @@ export function getDisplayValueFromType(type: string) {
case "vm":
return "VM";
case "pve":
return "PVE";
case "addon":
return "";
return "ADDON";
default:
return "";
}
@@ -36,10 +37,9 @@ export function LatestScripts({
onPageChange: (page: number) => void;
}) {
const latestScripts = useMemo(() => {
if (!items)
return [];
if (!items) return [];
const scripts = items.flatMap(category => category.scripts || []);
const scripts = items.flatMap((category) => category.scripts || []);
// Filter out duplicates by slug
const uniqueScriptsMap = new Map<string, Script>();
@@ -97,7 +97,7 @@ export function LatestScripts({
</div>
)}
<div className="min-w flex w-full flex-row flex-wrap gap-4">
{latestScripts.slice(startIndex, endIndex).map(script => (
{latestScripts.slice(startIndex, endIndex).map((script) => (
<Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30">
<CardHeader>
<CardTitle className="flex items-center gap-3">
@@ -108,15 +108,13 @@ export function LatestScripts({
height={64}
width={64}
alt=""
onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
className="h-11 w-11 object-contain"
/>
</div>
<div className="flex flex-col">
<p className="text-lg line-clamp-1">
{script.name}
{" "}
{getDisplayValueFromType(script.type)}
{script.name} {getDisplayValueFromType(script.type)}
</p>
<p className="text-sm text-muted-foreground flex items-center gap-1">
<CalendarPlus className="h-4 w-4" />
@@ -149,7 +147,7 @@ export function LatestScripts({
export function MostViewedScripts({ items }: { items: Category[] }) {
const mostViewedScripts = items.reduce((acc: Script[], category) => {
const foundScripts = category.scripts.filter(script => mostPopularScripts.includes(script.slug));
const foundScripts = category.scripts.filter((script) => mostPopularScripts.includes(script.slug));
return acc.concat(foundScripts);
}, []);
@@ -161,7 +159,7 @@ export function MostViewedScripts({ items }: { items: Category[] }) {
</>
)}
<div className="min-w flex w-full flex-row flex-wrap gap-4">
{mostViewedScripts.map(script => (
{mostViewedScripts.map((script) => (
<Card key={script.slug} className="min-w-[250px] flex-1 flex-grow bg-accent/30">
<CardHeader>
<CardTitle className="flex items-center gap-3">
@@ -172,15 +170,13 @@ export function MostViewedScripts({ items }: { items: Category[] }) {
height={64}
width={64}
alt=""
onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
className="h-11 w-11 object-contain"
/>
</div>
<div className="flex flex-col">
<p className="line-clamp-1 text-lg">
{script.name}
{" "}
{getDisplayValueFromType(script.type)}
{script.name} {getDisplayValueFromType(script.type)}
</p>
<p className="flex items-center gap-1 text-sm text-muted-foreground">
<CalendarPlus className="h-4 w-4" />

View File

@@ -14,6 +14,7 @@ import { basePath } from "@/config/site-config";
import { extractDate } from "@/lib/time";
import DisableDescription from "./script-items/disable-description";
import { formattedBadge } from "@/components/command-menu";
import { getDisplayValueFromType } from "./script-info-blocks";
import DefaultPassword from "./script-items/default-password";
import InstallCommand from "./script-items/install-command";
@@ -31,7 +32,7 @@ type ScriptItemProps = {
function ScriptHeader({ item }: { item: Script }) {
const defaultInstallMethod = item.install_methods?.[0];
const os = defaultInstallMethod?.resources?.os || "Proxmox Node";
const os = defaultInstallMethod?.resources?.os || (item.type === "addon" ? "Existing LXC or Proxmox Node" : "Proxmox Node");
const version = defaultInstallMethod?.resources?.version || "";
return (
@@ -55,9 +56,7 @@ function ScriptHeader({ item }: { item: Script }) {
<h1 className="text-2xl font-semibold tracking-tight flex items-center gap-2">
{item.name}
<VersionInfo item={item} />
<span className="inline-flex items-center rounded-md bg-accent/30 px-2 py-1 text-sm">
{getDisplayValueFromType(item.type)}
</span>
{formattedBadge(item.type)}
</h1>
<div className="mt-1 flex items-center gap-3 text-sm text-muted-foreground">
<span>

View File

@@ -36,17 +36,24 @@ const TooltipBadge: React.FC<TooltipProps> = ({ variant, label, content }) => (
export default function Tooltips({ item }: { item: Script }) {
return (
<div className="flex items-center gap-2">
{item.privileged && (
{item.privileged && item.type !== "addon" && (
<TooltipBadge variant="warning" label="Privileged" content="This script will be run in a privileged LXC" />
)}
{item.updateable && item.type !== "pve" && (
{item.updateable && item.type !== "pve" && item.type !== "addon" && (
<TooltipBadge
variant="success"
label="Updateable"
content={`To Update ${item.name}, run the command below (or type update) in the LXC Console.`}
/>
)}
{!item.updateable && item.type !== "pve" && <TooltipBadge variant="failure" label="Not Updateable" />}
{item.updateable && item.type === "addon" && (
<TooltipBadge
variant="success"
label="Updateable"
content={`Run update_${item.slug} to update or use the bash command inside the LXC.`}
/>
)}
{!item.updateable && item.type !== "pve" && item.type !== "addon" && <TooltipBadge variant="failure" label="Not Updateable" />}
</div>
);
}

View File

@@ -32,6 +32,11 @@ function ScriptContent() {
.flat()
.find(script => script.slug === selectedScript);
setItem(script);
if (script) {
document.title = `${script.name} | Proxmox VE Helper-Scripts`;
}
} else {
document.title = "Proxmox VE Helper-Scripts";
}
}, [selectedScript, links]);

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apk add --no-cache ca-certificates openssl
msg_ok "Installed Dependencies"
msg_info "Setup Docker Repository"
$STD apk add --no-cache docker docker-cli docker-compose openrc
msg_ok "Setup Docker Repository"
msg_info "Enabling Docker Service"
$STD rc-update add docker boot
$STD service docker start
msg_ok "Enabled Docker Service"
echo "${TAB3}Choose the database for Komodo installation:"
echo "${TAB3}1) MongoDB (recommended)"
echo "${TAB3}2) FerretDB"
read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in
1)
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
2)
DB_COMPOSE_FILE="ferretdb.compose.yaml"
;;
*)
echo "Invalid choice. Defaulting to MongoDB."
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
esac
mkdir -p /opt/komodo
cd /opt/komodo
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/$DB_COMPOSE_FILE" -o "$(basename "$DB_COMPOSE_FILE")"
msg_info "Setup Komodo Environment"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env" -o "/opt/komodo/compose.env"
DB_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
PASSKEY=$(openssl rand -base64 24 | tr -d '/+=')
WEBHOOK_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
JWT_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
sed -i "s/^KOMODO_DB_USERNAME=.*/KOMODO_DB_USERNAME=komodo_admin/" /opt/komodo/compose.env
sed -i "s/^KOMODO_DB_PASSWORD=.*/KOMODO_DB_PASSWORD=${DB_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_PASSKEY=.*/KOMODO_PASSKEY=${PASSKEY}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_WEBHOOK_SECRET=.*/KOMODO_WEBHOOK_SECRET=${WEBHOOK_SECRET}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_JWT_SECRET=.*/KOMODO_JWT_SECRET=${JWT_SECRET}/" /opt/komodo/compose.env
msg_ok "Setup Komodo Environment"
msg_info "Initialize Komodo"
$STD docker compose -p komodo -f "/opt/komodo/$DB_COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d
msg_ok "Initialized Komodo"
motd_ssh
customize
msg_info "Cleaning up"
$STD apk cache clean
msg_ok "Cleaned"

View File

@@ -14,7 +14,7 @@ network_check
update_os
read -r -p "${TAB3}Enter PostgreSQL version (15/16/17): " ver
[[ $ver =~ ^(15|16|17)$ ]] || { echo "Invalid version"; exit 1; }
[[ $ver =~ ^(15|16|17)$ ]] || { echo "Invalid version"; exit 64; }
msg_info "Installing PostgreSQL ${ver}"
$STD apk add --no-cache postgresql${ver} postgresql${ver}-contrib postgresql${ver}-openrc sudo

View File

@@ -25,7 +25,7 @@ case $version in
;;
*)
msg_error "Invalid JDK version selected. Please enter 8, 11, 17 or 21."
exit 1
exit 64
;;
esac
;;
@@ -39,7 +39,7 @@ case $version in
;;
*)
msg_error "Invalid JDK version selected. Please enter 11, 17 or 21."
exit 1
exit 64
;;
esac
;;
@@ -53,13 +53,13 @@ case $version in
;;
*)
msg_error "Invalid JDK version selected. Please enter 17 or 21."
exit 1
exit 64
;;
esac
;;
*)
msg_error "Invalid Tomcat version selected. Please enter 9, 10.1 or 11."
exit 1
exit 64
;;
esac

View File

@@ -59,7 +59,7 @@ mkdir -p /opt/booklore/dist
JAR_PATH=$(find /opt/booklore/booklore-api/build/libs -maxdepth 1 -type f -name "booklore-api-*.jar" ! -name "*plain*" | head -n1)
if [[ -z "$JAR_PATH" ]]; then
msg_error "Backend JAR not found"
exit 1
exit 153
fi
cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend"

View File

@@ -1,39 +0,0 @@
#!/bin/bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://coolify.io/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
git \
openssl
msg_ok "Installed Dependencies"
msg_warn "WARNING: This script will run an external installer from a third-party source (https://coolify.io/)."
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://cdn.coollabs.io/coolify/install.sh"
echo
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg_error "Aborted by user. No changes have been made."
exit 10
fi
msg_info "Installing Coolify (Patience - this installs Docker and pulls containers)"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Installed Coolify"
motd_ssh
customize
cleanup_lxc

View File

@@ -86,7 +86,7 @@ EOF
msg_ok "Docker TCP socket available on $socket"
else
msg_error "Docker failed to restart. Check journalctl -xeu docker.service"
exit 1
exit 150
fi
fi

View File

@@ -1,64 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dockge.kuma.pet/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
DOCKER_LATEST_VERSION=$(get_latest_github_release "moby/moby")
msg_info "Installing Docker $DOCKER_LATEST_VERSION (with Compose, Buildx)"
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p $(dirname $DOCKER_CONFIG_PATH)
echo -e '{\n "log-driver": "journald"\n}' >/etc/docker/daemon.json
$STD sh <(curl -fsSL https://get.docker.com)
msg_ok "Installed Docker $DOCKER_LATEST_VERSION"
msg_info "Installing Dockge"
mkdir -p /opt/{dockge,stacks}
curl -fsSL "https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml" -o "/opt/dockge/compose.yaml"
cd /opt/dockge
$STD docker compose up -d
msg_ok "Installed Dockge"
read -r -p "${TAB3}Would you like to add Immich? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Immich compose.yaml"
mkdir -p /opt/stacks/immich
curl -fsSL "https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml" -o "/opt/stacks/immich/compose.yaml"
curl -fsSL "https://github.com/immich-app/immich/releases/latest/download/example.env" -o "/opt/stacks/immich/.env"
msg_ok "Added Immich compose.yaml"
fi
read -r -p "${TAB3}Would you like to add Home Assistant? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Adding Home Assistant compose.yaml"
mkdir -p /opt/stacks/homeassistant
cat <<EOF >/opt/stacks/homeassistant/compose.yaml
version: "3"
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
privileged: true
network_mode: host
EOF
msg_ok "Added Home Assistant compose.yaml"
fi
motd_ssh
customize
cleanup_lxc

View File

@@ -1,40 +0,0 @@
#!/bin/bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dokploy.com/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y \
git \
openssl \
redis
msg_ok "Installed Dependencies"
msg_warn "WARNING: This script will run an external installer from a third-party source (https://dokploy.com/)."
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://dokploy.com/install.sh"
echo
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg_error "Aborted by user. No changes have been made."
exit 10
fi
msg_info "Installing Dokploy (Patience - this installs Docker and pulls containers)"
$STD bash <(curl -sSL https://dokploy.com/install.sh)
msg_ok "Installed Dokploy"
motd_ssh
customize
cleanup_lxc

View File

@@ -21,7 +21,7 @@ msg_info "Fetching latest EMQX Enterprise version"
LATEST_VERSION=$(curl -fsSL https://www.emqx.com/en/downloads/enterprise | grep -oP '/en/downloads/enterprise/v\K[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -n1)
if [[ -z "$LATEST_VERSION" ]]; then
msg_error "Failed to determine latest EMQX version"
exit 1
exit 250
fi
msg_ok "Latest version: v$LATEST_VERSION"

View File

@@ -1,8 +1,7 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Authors: MickLesk (CanbiZ)
# Co-Authors: remz1337
# Authors: MickLesk (CanbiZ) | Co-Authors: remz1337
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://frigate.video/ | Github: https://github.com/blakeblackshear/frigate
@@ -17,7 +16,7 @@ update_os
source /etc/os-release
if [[ "$VERSION_ID" != "12" ]]; then
msg_error "Frigate requires Debian 12 (Bookworm) due to Python 3.11 dependencies"
exit 1
exit 238
fi
msg_info "Converting APT sources to DEB822 format"
@@ -85,6 +84,7 @@ $STD apt install -y \
tclsh \
libopenblas-dev \
liblapack-dev \
libgomp1 \
make \
moreutils
msg_ok "Installed Dependencies"
@@ -101,9 +101,16 @@ export NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
export TOKENIZERS_PARALLELISM=true
export TRANSFORMERS_NO_ADVISORY_WARNINGS=1
export OPENCV_FFMPEG_LOGLEVEL=8
export PYTHONWARNINGS="ignore:::numpy.core.getlimits"
export HAILORT_LOGGER_PATH=NONE
export TF_CPP_MIN_LOG_LEVEL=3
export TF_CPP_MIN_VLOG_LEVEL=3
export TF_ENABLE_ONEDNN_OPTS=0
export AUTOGRAPH_VERBOSITY=0
export GLOG_minloglevel=3
export GLOG_logtostderr=0
fetch_and_deploy_gh_release "frigate" "blakeblackshear/frigate" "tarball" "v0.16.4" "/opt/frigate"
fetch_and_deploy_gh_release "frigate" "blakeblackshear/frigate" "tarball" "v0.17.0" "/opt/frigate"
msg_info "Building Nginx"
$STD bash /opt/frigate/docker/main/build_nginx.sh
@@ -138,13 +145,19 @@ install -c -m 644 libusb-1.0.pc /usr/local/lib/pkgconfig
ldconfig
msg_ok "Built libUSB"
msg_info "Bootstrapping pip"
wget -q https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py
sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' /tmp/get-pip.py
$STD python3 /tmp/get-pip.py "pip"
rm -f /tmp/get-pip.py
msg_ok "Bootstrapped pip"
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
@@ -152,7 +165,7 @@ for i in {1..3}; do
done
msg_ok "Built Python Wheels"
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
NODE_VERSION="20" setup_nodejs
msg_info "Downloading Inference Models"
mkdir -p /models /openvino-model
@@ -183,6 +196,10 @@ $STD pip3 install -U /wheels/*.whl
ldconfig
msg_ok "Installed HailoRT Runtime"
msg_info "Installing MemryX Runtime"
$STD bash /opt/frigate/docker/main/install_memryx.sh
msg_ok "Installed MemryX Runtime"
msg_info "Installing OpenVino"
$STD pip3 install -r /opt/frigate/docker/main/requirements-ov.txt
msg_ok "Installed OpenVino"
@@ -209,6 +226,8 @@ $STD make version
cd /opt/frigate/web
$STD npm install
$STD npm run build
mv /opt/frigate/web/dist/BASE_PATH/monacoeditorwork/* /opt/frigate/web/dist/assets/
rm -rf /opt/frigate/web/dist/BASE_PATH
cp -r /opt/frigate/web/dist/* /opt/frigate/web/
sed -i '/^s6-svc -O \.$/s/^/#/' /opt/frigate/docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
msg_ok "Built Frigate Application"
@@ -224,6 +243,19 @@ 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"
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES="compute,video,utility"
TOKENIZERS_PARALLELISM=true
TRANSFORMERS_NO_ADVISORY_WARNINGS=1
OPENCV_FFMPEG_LOGLEVEL=8
PYTHONWARNINGS="ignore:::numpy.core.getlimits"
HAILORT_LOGGER_PATH=NONE
TF_CPP_MIN_LOG_LEVEL=3
TF_CPP_MIN_VLOG_LEVEL=3
TF_ENABLE_ONEDNN_OPTS=0
AUTOGRAPH_VERBOSITY=0
GLOG_minloglevel=3
GLOG_logtostderr=0
EOF
cat <<EOF >/config/config.yml
@@ -237,7 +269,6 @@ cameras:
input_args: -re -stream_loop -1 -fflags +genpts
roles:
- detect
- rtmp
detect:
height: 1080
width: 1920
@@ -255,6 +286,7 @@ ffmpeg:
detectors:
detector01:
type: openvino
device: AUTO
model:
width: 300
height: 300

View File

@@ -31,7 +31,7 @@ fi
if [[ -z "$KASM_URL" ]] || [[ -z "$KASM_VERSION" ]]; then
msg_error "Unable to detect latest Kasm release URL."
exit 1
exit 250
fi
msg_ok "Detected Kasm Workspaces version $KASM_VERSION"

View File

@@ -1,85 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://komo.do/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Setup Docker Repository"
setup_deb822_repo \
"docker" \
"https://download.docker.com/linux/$(get_os_info id)/gpg" \
"https://download.docker.com/linux/$(get_os_info id)" \
"$(get_os_info codename)" \
"stable" \
"$(dpkg --print-architecture)"
msg_ok "Setup Docker Repository"
msg_info "Installing Docker"
$STD apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
msg_ok "Installed Docker"
echo "${TAB3}Choose the database for Komodo installation:"
echo "${TAB3}1) MongoDB (recommended)"
echo "${TAB3}2) FerretDB"
read -rp "${TAB3}Enter your choice (default: 1): " DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in
1)
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
2)
DB_COMPOSE_FILE="ferretdb.compose.yaml"
;;
*)
echo "Invalid choice. Defaulting to MongoDB."
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
esac
mkdir -p /opt/komodo
cd /opt/komodo
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/$DB_COMPOSE_FILE" -o "/opt/komodo/$DB_COMPOSE_FILE"
msg_info "Setup Komodo Environment"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env" -o "/opt/komodo/compose.env"
DB_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
ADMIN_PASSWORD=$(openssl rand -base64 8 | tr -d '/+=')
PASSKEY=$(openssl rand -base64 24 | tr -d '/+=')
WEBHOOK_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
JWT_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
sed -i "s/^KOMODO_DB_USERNAME=.*/KOMODO_DB_USERNAME=komodo_admin/" /opt/komodo/compose.env
sed -i "s/^KOMODO_DB_PASSWORD=.*/KOMODO_DB_PASSWORD=${DB_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_INIT_ADMIN_PASSWORD=changeme/KOMODO_INIT_ADMIN_PASSWORD=${ADMIN_PASSWORD}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_PASSKEY=.*/KOMODO_PASSKEY=${PASSKEY}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_WEBHOOK_SECRET=.*/KOMODO_WEBHOOK_SECRET=${WEBHOOK_SECRET}/" /opt/komodo/compose.env
sed -i "s/^KOMODO_JWT_SECRET=.*/KOMODO_JWT_SECRET=${JWT_SECRET}/" /opt/komodo/compose.env
{
echo "Komodo Credentials"
echo ""
echo "Admin User : admin"
echo "Admin Password: $ADMIN_PASSWORD"
} >>~/komodo.creds
msg_ok "Setup Komodo Environment"
msg_info "Initialize Komodo"
$STD docker compose -p komodo -f /opt/komodo/$DB_COMPOSE_FILE --env-file /opt/komodo/compose.env up -d
msg_ok "Initialized Komodo"
motd_ssh
customize
cleanup_lxc

View File

@@ -28,7 +28,7 @@ $STD apt install -y \
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv
POSTGRES_VERSION="16" setup_postgresql
PG_VERSION="16" setup_postgresql
NODE_MODULE="yarn" NODE_VERSION="24" setup_nodejs
fetch_and_deploy_gh_release "mealie" "mealie-recipes/mealie" "tarball" "latest" "/opt/mealie"
PG_DB_NAME="mealie_db" PG_DB_USER="mealie_user" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db

View File

@@ -51,7 +51,7 @@ while true; do
attempts=$((attempts + 1))
if [[ "$attempts" -ge 3 ]]; then
msg_error "Maximum attempts reached. Exiting."
exit 1
exit 254
fi
done
@@ -76,11 +76,11 @@ for i in {1..60}; do
elif [[ "$STATUS" == "unhealthy" ]]; then
msg_error "NPMplus container is unhealthy! Check logs."
docker logs "$CONTAINER_ID"
exit 1
exit 150
fi
fi
sleep 2
[[ $i -eq 60 ]] && msg_error "NPMplus container did not become healthy within 120s." && docker logs "$CONTAINER_ID" && exit 1
[[ $i -eq 60 ]] && msg_error "NPMplus container did not become healthy within 120s." && docker logs "$CONTAINER_ID" && exit 150
done
msg_ok "Builded and started NPMplus"

View File

@@ -78,11 +78,11 @@ if curl -fL# -C - -o "$TMP_TAR" "$OLLAMA_URL"; then
msg_ok "Installed Ollama ${RELEASE}"
else
msg_error "Extraction failed archive corrupt or incomplete"
exit 1
exit 251
fi
else
msg_error "Download failed $OLLAMA_URL not reachable"
exit 1
exit 250
fi
msg_info "Creating ollama User and Group"

View File

@@ -59,7 +59,7 @@ EOF
else
msg_error "Failed to download or verify GPG key from $KEY_URL"
[[ -f "$TMP_KEY_CONTENT" ]] && rm -f "$TMP_KEY_CONTENT"
exit 1
exit 250
fi
rm -f "$TMP_KEY_CONTENT"

View File

@@ -38,6 +38,7 @@ sed -i "s|^DATABASE_URL=.*|DATABASE_URL=\"postgresql://$PG_DB_USER:$PG_DB_PASS@l
sed -i "s|^MEILI_HOST=.*|MEILI_HOST=http://localhost:7700|g" /opt/openarchiver/.env
sed -i "s|^MEILI_MASTER_KEY=.*|MEILI_MASTER_KEY=$MEILISEARCH_MASTER_KEY|g" /opt/openarchiver/.env
sed -i "s|^REDIS_HOST=.*|REDIS_HOST=localhost|g" /opt/openarchiver/.env
sed -i "s|^REDIS_USER=.*|REDIS_USER=|g" /opt/openarchiver/.env
sed -i "s|^REDIS_PASSWORD=.*|REDIS_PASSWORD=|g" /opt/openarchiver/.env
sed -i "s|^STORAGE_LOCAL_ROOT_PATH=.*|STORAGE_LOCAL_ROOT_PATH=/opt/openarchiver-data|g" /opt/openarchiver/.env
sed -i "s|^JWT_SECRET=.*|JWT_SECRET=$JWT_KEY|g" /opt/openarchiver/.env

View File

@@ -34,7 +34,7 @@ for server in "${servers[@]}"; do
done
if ((attempt >= MAX_ATTEMPTS)); then
msg_error "No more attempts - aborting script!"
exit 1
exit 254
fi
done

View File

@@ -16,7 +16,7 @@ update_os
read -r -p "${TAB3}Enter PostgreSQL version (15/16/17/18): " ver
[[ $ver =~ ^(15|16|17|18)$ ]] || {
echo "Invalid version"
exit 1
exit 64
}
PG_VERSION=$ver setup_postgresql

View File

@@ -0,0 +1,74 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Dictionarry-Hub/profilarr
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-dev \
libffi-dev \
libssl-dev \
git
msg_ok "Installed Dependencies"
PYTHON_VERSION="3.12" setup_uv
NODE_VERSION="22" setup_nodejs
msg_info "Creating directories"
mkdir -p /opt/profilarr \
/config
msg_ok "Created directories"
fetch_and_deploy_gh_release "profilarr" "Dictionarry-Hub/profilarr" "tarball"
msg_info "Installing Python Dependencies"
cd /opt/profilarr/backend
$STD uv venv /opt/profilarr/backend/.venv
sed 's/==/>=/g' requirements.txt >requirements-relaxed.txt
$STD uv pip install --python /opt/profilarr/backend/.venv/bin/python -r requirements-relaxed.txt
rm -f requirements-relaxed.txt
msg_ok "Installed Python Dependencies"
msg_info "Building Frontend"
cd /opt/profilarr/frontend
$STD npm install
$STD npm run build
cp -r dist /opt/profilarr/backend/app/static
msg_ok "Built Frontend"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/profilarr.service
[Unit]
Description=Profilarr - Configuration Management Platform for Radarr/Sonarr
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/profilarr/backend
Environment="PATH=/opt/profilarr/backend/.venv/bin:/usr/local/bin:/usr/bin:/bin"
Environment="PYTHONPATH=/opt/profilarr/backend"
ExecStart=/opt/profilarr/backend/.venv/bin/gunicorn --bind 0.0.0.0:6868 --timeout 600 app.main:create_app()
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now profilarr
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -25,7 +25,7 @@ if useradd -r -m -d /opt/pulse-home -s /usr/sbin/nologin pulse; then
msg_ok "Created User"
else
msg_error "User creation failed"
exit 1
exit 71
fi
mkdir -p /etc/pulse

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://runtipi.io/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_warn "WARNING: This script will run an external installer from a third-party source (https://runtipi.io/)."
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ https://raw.githubusercontent.com/runtipi/runtipi/master/scripts/install.sh"
echo
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
msg_error "Aborted by user. No changes have been made."
exit 10
fi
msg_info "Installing Runtipi (Patience)"
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
cd /opt
curl -fsSL "https://raw.githubusercontent.com/runtipi/runtipi/master/scripts/install.sh" -o "install.sh"
chmod +x install.sh
$STD ./install.sh
chmod 666 /opt/runtipi/state/settings.json
rm -f /opt/install.sh
msg_ok "Installed Runtipi"
motd_ssh
customize
cleanup_lxc

View File

@@ -17,12 +17,14 @@ 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"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1]' /opt/sparkyfitness/package.json)"
NODE_VERSION="25" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
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"
@@ -50,8 +52,8 @@ msg_ok "Built Backend"
msg_info "Building Frontend (Patience)"
cd /opt/sparkyfitness/SparkyFitnessFrontend
$STD npm install
$STD npm run build
$STD pnpm install
$STD pnpm run build
cp -a /opt/sparkyfitness/SparkyFitnessFrontend/dist/. /var/www/sparkyfitness/
msg_ok "Built Frontend"

View File

@@ -34,7 +34,7 @@ while true; do
[Nn]|[Nn][Oo]|"")
msg_error "Terms not accepted. Installation cannot proceed."
msg_error "Please review the terms and run the script again if you wish to proceed."
exit 1
exit 254
;;
*)
msg_error "Invalid response. Please enter 'y' for yes or 'n' for no."
@@ -47,7 +47,7 @@ DOWNLOAD_URL=$(curl -s "https://www.splunk.com/en_us/download/splunk-enterprise.
RELEASE=$(echo "$DOWNLOAD_URL" | sed 's|.*/releases/\([^/]*\)/.*|\1|')
$STD curl -fsSL -o "splunk-enterprise.tgz" "$DOWNLOAD_URL" || {
msg_error "Failed to download Splunk Enterprise from the provided link."
exit 1
exit 250
}
$STD tar -xzf "splunk-enterprise.tgz" -C /opt
rm -f "splunk-enterprise.tgz"

View File

@@ -44,7 +44,20 @@ $STD timescaledb-tune -yes -memory "$ram_for_tsdb"MB
$STD systemctl restart postgresql
msg_ok "Installed TimescaleDB"
PG_DB_NAME="tracearr_db" PG_DB_USER="tracearr" PG_DB_EXTENSIONS="timescaledb,timescaledb_toolkit" setup_postgresql_db
PG_DB_NAME="tracearr_db" PG_DB_USER="tracearr" PG_DB_EXTENSIONS="timescaledb,timescaledb_toolkit" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
msg_info "Installing tailscale"
setup_deb822_repo \
"tailscale" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/$(get_os_info codename).noarmor.gpg" \
"https://pkgs.tailscale.com/stable/$(get_os_info id)/" \
"$(get_os_info codename)"
$STD apt install -y tailscale
# Tracearr runs tailscaled in user mode, disable the service.
$STD systemctl disable --now tailscaled
$STD systemctl stop tailscaled
msg_ok "Installed tailscale"
fetch_and_deploy_gh_release "tracearr" "connorgallopo/Tracearr" "tarball" "latest" "/opt/tracearr.build"
msg_info "Building Tracearr"
@@ -75,6 +88,7 @@ msg_info "Configuring Tracearr"
$STD useradd -r -s /bin/false -U tracearr
$STD chown -R tracearr:tracearr /opt/tracearr
install -d -m 750 -o tracearr -g tracearr /data/tracearr
install -d -m 750 -o tracearr -g tracearr /data/backup
export JWT_SECRET=$(openssl rand -hex 32)
export COOKIE_SECRET=$(openssl rand -hex 32)
cat <<EOF >/data/tracearr/.env
@@ -89,7 +103,6 @@ JWT_SECRET=$JWT_SECRET
COOKIE_SECRET=$COOKIE_SECRET
APP_VERSION=$(cat /root/.tracearr)
#CORS_ORIGIN=http://localhost:5173
#MOBILE_BETA_MODE=true
EOF
chmod 600 /data/tracearr/.env
chown -R tracearr:tracearr /data/tracearr
@@ -140,6 +153,7 @@ if [ -f \$pg_config_file ]; then
fi
fi
systemctl restart postgresql
sudo -u postgres psql -c "ALTER USER tracearr WITH SUPERUSER;"
EOF
chmod +x /data/tracearr/prestart.sh
cat <<EOF >/lib/systemd/system/tracearr.service

View File

@@ -16,13 +16,13 @@ update_os
if [[ "${CTTYPE:-1}" != "0" ]]; then
msg_error "UniFi OS Server requires a privileged LXC container."
msg_error "Recreate the container with unprivileged=0."
exit 1
exit 10
fi
if [[ ! -e /dev/net/tun ]]; then
msg_error "Missing /dev/net/tun in container."
msg_error "Enable TUN/TAP (var_tun=yes) or add /dev/net/tun passthrough."
exit 1
exit 236
fi
msg_info "Installing dependencies"
@@ -48,7 +48,7 @@ TEMP_JSON="$(mktemp)"
if ! curl -fsSL "$API_URL" -o "$TEMP_JSON"; then
rm -f "$TEMP_JSON"
msg_error "Failed to fetch data from Ubiquiti API"
exit 1
exit 250
fi
LATEST=$(jq -r '
._embedded.firmware
@@ -62,7 +62,7 @@ UOS_URL=$(echo "$LATEST" | jq -r '._links.data.href')
rm -f "$TEMP_JSON"
if [[ -z "$UOS_URL" || -z "$UOS_VERSION" || "$UOS_URL" == "null" ]]; then
msg_error "Failed to parse UniFi OS Server version or download URL"
exit 1
exit 250
fi
msg_ok "Found UniFi OS Server ${UOS_VERSION}"

View File

@@ -31,7 +31,7 @@ if gpg --verify /tmp/zerotier-install.sh >/dev/null 2>&1; then
$STD bash /tmp/zerotier-install.sh
else
msg_warn "Could not verify signature of Zerotier-One install script. Exiting..."
exit 1
exit 250
fi
msg_ok "Setup Zerotier-One"

View File

@@ -79,7 +79,7 @@ setting_up_container() {
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" = "" ]; then
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
echo -e "${NETWORK}Check Network Settings"
exit 1
exit 121
fi
msg_ok "Set up Container OS"
msg_ok "Network Connected: ${BL}$(ip addr show | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1 | tail -n1)${CL}"
@@ -99,7 +99,7 @@ network_check() {
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
else
echo -e "${NETWORK}Check Network Settings"
exit 1
exit 122
fi
fi
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
@@ -119,12 +119,12 @@ update_os() {
local tools_content
tools_content=$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) || {
msg_error "Failed to download tools.func"
exit 6
exit 115
}
source /dev/stdin <<<"$tools_content"
if ! declare -f fetch_and_deploy_gh_release >/dev/null 2>&1; then
msg_error "tools.func loaded but incomplete — missing expected functions"
exit 6
exit 115
fi
msg_ok "Updated Container OS"
post_progress_to_api

View File

@@ -124,6 +124,7 @@ detect_repo_source
# * Generic/Shell errors (1-3, 10, 124-132, 134, 137, 139, 141, 143-146)
# * curl/wget errors (4-8, 16, 18, 22-28, 30, 32-36, 39, 44-48, 51-52, 55-57, 59, 61, 63, 75, 78-79, 92, 95)
# * Package manager errors (APT, DPKG: 100-102, 255)
# * Script Validation & Setup (103-123)
# * BSD sysexits (64-78)
# * Systemd/Service errors (150-154)
# * Python/pip/uv errors (160-162)
@@ -131,7 +132,9 @@ detect_repo_source
# * MySQL/MariaDB errors (180-183)
# * MongoDB errors (190-193)
# * Proxmox custom codes (200-231)
# * Tools & Addon Scripts (232-238)
# * Node.js/npm errors (239, 243, 245-249)
# * Application Install/Update errors (250-254)
# - Returns description string for given exit code
# ------------------------------------------------------------------------------
explain_exit_code() {
@@ -189,6 +192,29 @@ explain_exit_code() {
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
# --- Script Validation & Setup (103-123) ---
103) echo "Validation: Shell is not Bash" ;;
104) echo "Validation: Not running as root (or invoked via sudo)" ;;
105) echo "Validation: Proxmox VE version not supported" ;;
106) echo "Validation: Architecture not supported (ARM / PiMox)" ;;
107) echo "Validation: Kernel key parameters unreadable" ;;
108) echo "Validation: Kernel key limits exceeded" ;;
109) echo "Proxmox: No available container ID after max attempts" ;;
110) echo "Proxmox: Failed to apply default.vars" ;;
111) echo "Proxmox: App defaults file not available" ;;
112) echo "Proxmox: Invalid install menu option" ;;
113) echo "LXC: Under-provisioned — user aborted update" ;;
114) echo "LXC: Storage too low — user aborted update" ;;
115) echo "Download: install.func download failed or incomplete" ;;
116) echo "Proxmox: Default bridge vmbr0 not found" ;;
117) echo "LXC: Container did not reach running state" ;;
118) echo "LXC: No IP assigned to container after timeout" ;;
119) echo "Proxmox: No valid storage for rootdir content" ;;
120) echo "Proxmox: No valid storage for vztmpl content" ;;
121) echo "LXC: Container network not ready (no IP after retries)" ;;
122) echo "LXC: No internet connectivity — user declined to continue" ;;
123) echo "LXC: Local IP detection failed" ;;
# --- BSD sysexits.h (64-78) ---
64) echo "Usage error (wrong arguments)" ;;
65) echo "Data format error (bad input data)" ;;
@@ -276,8 +302,18 @@ explain_exit_code() {
223) echo "Proxmox: Template not available after download" ;;
224) echo "Proxmox: PBS storage is for backups only" ;;
225) echo "Proxmox: No template available for OS/Version" ;;
226) echo "Proxmox: VM disk import or post-creation setup failed" ;;
231) echo "Proxmox: LXC stack upgrade failed" ;;
# --- Tools & Addon Scripts (232-238) ---
232) echo "Tools: Wrong execution environment (run on PVE host, not inside LXC)" ;;
233) echo "Tools: Application not installed (update prerequisite missing)" ;;
234) echo "Tools: No LXC containers found or available" ;;
235) echo "Tools: Backup or restore operation failed" ;;
236) echo "Tools: Required hardware not detected" ;;
237) echo "Tools: Dependency package installation failed" ;;
238) echo "Tools: OS or distribution not supported for this addon" ;;
# --- Node.js / npm / pnpm / yarn (239-249) ---
239) echo "npm/Node.js: Unexpected runtime error or dependency failure" ;;
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
@@ -287,6 +323,13 @@ explain_exit_code() {
248) echo "Node.js: Invalid C++ addon / N-API failure" ;;
249) echo "npm/pnpm/yarn: Unknown fatal error" ;;
# --- Application Install/Update Errors (250-254) ---
250) echo "App: Download failed or version not determined" ;;
251) echo "App: File extraction failed (corrupt or incomplete archive)" ;;
252) echo "App: Required file or resource not found" ;;
253) echo "App: Data migration required — update aborted" ;;
254) echo "App: User declined prompt or input timed out" ;;
# --- DPKG ---
255) echo "DPKG: Fatal internal error" ;;
@@ -350,6 +393,11 @@ get_error_text() {
logfile="$BUILD_LOG"
fi
# Try SILENT_LOGFILE as last resort (captures $STD command output)
if [[ -z "$logfile" || ! -s "$logfile" ]] && [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
logfile="$SILENT_LOGFILE"
fi
if [[ -n "$logfile" && -s "$logfile" ]]; then
tail -n 20 "$logfile" 2>/dev/null | sed 's/\r$//' | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'
fi
@@ -395,6 +443,13 @@ get_full_log() {
fi
fi
# Fall back to SILENT_LOGFILE (captures $STD command output)
if [[ -z "$logfile" || ! -s "$logfile" ]]; then
if [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
logfile="$SILENT_LOGFILE"
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 |
@@ -833,7 +888,7 @@ post_update_to_api() {
esac
# For failed/unknown status, resolve exit code and error description
local short_error=""
local short_error="" medium_error=""
if [[ "$pb_status" == "failed" ]] || [[ "$pb_status" == "unknown" ]]; then
if [[ "$raw_exit_code" =~ ^[0-9]+$ ]]; then
exit_code="$raw_exit_code"
@@ -853,6 +908,18 @@ post_update_to_api() {
short_error=$(json_escape "$(explain_exit_code "$exit_code")")
error_category=$(categorize_error "$exit_code")
[[ -z "$error" ]] && error="Unknown error"
# Build medium error for attempt 2: explanation + last 100 log lines (≤16KB)
# This is the critical middle ground between full 120KB log and generic-only description
local medium_log=""
medium_log=$(get_full_log 16384) || true # 16KB max
if [[ -z "$medium_log" ]]; then
medium_log=$(get_error_text) || true
fi
local medium_full
medium_full=$(build_error_string "$exit_code" "$medium_log")
medium_error=$(json_escape "$medium_full")
[[ -z "$medium_error" ]] && medium_error="$short_error"
fi
# Calculate duration if timer was started
@@ -911,7 +978,7 @@ EOF
return 0
fi
# ── Attempt 2: Short error text (no full log) ──
# ── Attempt 2: Medium error text (truncated log ≤16KB instead of full 120KB) ──
sleep 1
local RETRY_PAYLOAD
RETRY_PAYLOAD=$(
@@ -931,7 +998,7 @@ EOF
"pve_version": "${pve_version}",
"method": "${METHOD:-default}",
"exit_code": ${exit_code},
"error": "${short_error}",
"error": "${medium_error}",
"error_category": "${error_category}",
"install_duration": ${duration},
"cpu_vendor": "${cpu_vendor}",
@@ -954,7 +1021,7 @@ EOF
return 0
fi
# ── Attempt 3: Minimal payload (bare minimum to set status) ──
# ── Attempt 3: Minimal payload with medium error (bare minimum to set status) ──
sleep 2
local MINIMAL_PAYLOAD
MINIMAL_PAYLOAD=$(
@@ -966,7 +1033,7 @@ EOF
"nsapp": "${NSAPP:-unknown}",
"status": "${pb_status}",
"exit_code": ${exit_code},
"error": "${short_error}",
"error": "${medium_error}",
"error_category": "${error_category}",
"install_duration": ${duration}
}

View File

@@ -119,7 +119,7 @@ maxkeys_check() {
# Exit if kernel parameters are unavailable
if [[ "$per_user_maxkeys" -eq 0 || "$per_user_maxbytes" -eq 0 ]]; then
msg_error "Unable to read kernel key parameters. Ensure proper permissions."
exit 1
exit 107
fi
# Fetch key usage for user ID 100000 (typical for containers)
@@ -148,7 +148,7 @@ maxkeys_check() {
# Provide next steps if issues are detected
if [[ "$failure" -eq 1 ]]; then
msg_error "Kernel key limits exceeded - see suggestions above"
exit 1
exit 108
fi
# Silent success - only show errors if they exist
@@ -355,7 +355,7 @@ get_valid_container_id() {
attempts=$((attempts + 1))
if [[ $attempts -ge $max_attempts ]]; then
msg_error "Could not find available container ID after $max_attempts attempts"
exit 1
exit 109
fi
done
@@ -2035,7 +2035,7 @@ advanced_settings() {
else
whiptail --msgbox "Default bridge 'vmbr0' not found!\n\nPlease configure a network bridge in Proxmox first." 10 58
msg_error "Default bridge 'vmbr0' not found"
exit 1
exit 116
fi
else
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
@@ -3023,7 +3023,7 @@ install_script() {
3 | mydefaults | MYDEFAULTS | userdefaults | USERDEFAULTS)
default_var_settings || {
msg_error "Failed to apply default.vars"
exit 1
exit 110
}
defaults_target="/usr/local/community-scripts/default.vars"
break
@@ -3040,7 +3040,7 @@ install_script() {
break
else
msg_error "No App Defaults available for ${APP}"
exit 1
exit 111
fi
;;
"$SETTINGS_OPTION" | settings | SETTINGS)
@@ -3051,7 +3051,7 @@ install_script() {
;;
*)
msg_error "Invalid option: $CHOICE"
exit 1
exit 112
;;
esac
done
@@ -3135,7 +3135,7 @@ check_container_resources() {
read -r prompt </dev/tty
if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then
msg_error "Aborted: under-provisioned LXC (${current_cpu} CPU/${current_ram}MB RAM < ${var_cpu} CPU/${var_ram}MB RAM)"
exit 1
exit 113
fi
else
echo -e ""
@@ -3158,7 +3158,7 @@ check_container_storage() {
read -r prompt </dev/tty
if [[ ! ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_error "Aborted: storage too low (${usage}% used)"
exit 1
exit 114
fi
fi
}
@@ -3446,7 +3446,7 @@ start() {
3)
clear
exit_script
exit
exit 0
;;
esac
ensure_profile_loaded
@@ -3556,7 +3556,7 @@ build_container() {
export FUNCTIONS_FILE_PATH="$(curl -fsSL "$_func_url")"
if [[ -z "$FUNCTIONS_FILE_PATH" || ${#FUNCTIONS_FILE_PATH} -lt 100 ]]; then
msg_error "Failed to download install functions from: $_func_url"
exit 1
exit 115
fi
# Core exports for install.func
@@ -3938,7 +3938,7 @@ EOF
local ct_status
ct_status=$(pct status "$CTID" 2>/dev/null || echo "unknown")
msg_error "LXC Container did not reach running state (status: ${ct_status})"
exit 1
exit 117
fi
done
@@ -3967,7 +3967,7 @@ EOF
echo " • Verify static IP configuration (if using static IP)"
echo " • Check Proxmox firewall rules"
echo " • If using Tailscale: Disable MagicDNS temporarily"
exit 1
exit 118
fi
# Verify basic connectivity (ping test)
@@ -4094,15 +4094,8 @@ EOF'
# that sends "configuring" status AFTER the host already reported "failed"
export CONTAINER_INSTALLING=true
# 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]}
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local lxc_exit=$?
unset CONTAINER_INSTALLING
@@ -4164,19 +4157,9 @@ EOF'
build_log_copied=true
fi
# Copy and append INSTALL_LOG from container (with timeout to prevent hangs)
# Copy and append INSTALL_LOG from container
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
if pct pull "$CTID" "/root/.install-${SESSION_ID}.log" "$temp_install_log" 2>/dev/null; then
{
echo "================================================================================"
echo "PHASE 2: APPLICATION INSTALLATION (Container)"
@@ -4184,24 +4167,8 @@ EOF'
cat "$temp_install_log"
echo ""
} >>"$combined_log"
rm -f "$temp_install_log"
install_log_copied=true
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
@@ -4387,7 +4354,8 @@ EOF'
echo ""
echo -en "${YW}Select option [1-${max_option}] (default: 1, auto-remove in 60s): ${CL}"
if read -t 60 -r response </dev/tty; then
local response=""
if read -t 60 -r response; then
case "${response:-1}" in
1)
# Remove container
@@ -4474,9 +4442,8 @@ EOF'
# Re-run install script in existing container (don't destroy/recreate)
set +Eeuo pipefail
trap - ERR
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]}
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
local apt_retry_exit=$?
set -Eeuo pipefail
trap 'error_handler' ERR
@@ -4586,9 +4553,6 @@ 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
@@ -5004,11 +4968,11 @@ create_lxc_container() {
# Storage capability check
check_storage_support "rootdir" || {
msg_error "No valid storage found for 'rootdir' [Container]"
exit 1
exit 119
}
check_storage_support "vztmpl" || {
msg_error "No valid storage found for 'vztmpl' [Template]"
exit 1
exit 120
}
# Template storage selection
@@ -5286,7 +5250,7 @@ create_lxc_container() {
}
else
msg_custom "🚫" "${YW}" "Installation cancelled"
exit 1
exit 0
fi
else
msg_error "No ${PCT_OSTYPE} templates available"

View File

@@ -276,7 +276,7 @@ shell_check() {
msg_error "Your default shell is currently not set to Bash. To use these scripts, please switch to the Bash shell."
echo -e "\nExiting..."
sleep 2
exit 1
exit 103
fi
}
@@ -293,7 +293,7 @@ root_check() {
msg_error "Please run this script as root."
echo -e "\nExiting..."
sleep 2
exit 1
exit 104
fi
}
@@ -314,7 +314,7 @@ pve_check() {
if ((MINOR < 0 || MINOR > 9)); then
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported: Proxmox VE version 8.0 8.9"
exit 1
exit 105
fi
return 0
fi
@@ -325,7 +325,7 @@ pve_check() {
if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported."
msg_error "Supported: Proxmox VE version 9.0 9.1"
exit 1
exit 105
fi
return 0
fi
@@ -333,7 +333,7 @@ pve_check() {
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported versions: Proxmox VE 8.0 8.9 or 9.0 9.1"
exit 1
exit 105
}
# ------------------------------------------------------------------------------
@@ -348,7 +348,7 @@ arch_check() {
msg_error "This script will not work with PiMox (ARM architecture detected)."
msg_warn "Visit https://github.com/asylumexp/Proxmox for ARM64 support."
sleep 2
exit 1
exit 106
fi
}
@@ -848,7 +848,9 @@ exit_script() {
get_header() {
local app_name=$(echo "${APP,,}" | tr -d ' ')
local app_type=${APP_TYPE:-ct} # Default to 'ct' if not set
local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/${app_type}/headers/${app_name}"
local header_dir="${app_type}"
[[ "$app_type" == "addon" ]] && header_dir="tools"
local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/${header_dir}/headers/${app_name}"
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
mkdir -p "$(dirname "$local_header_path")"
@@ -930,18 +932,13 @@ is_alpine() {
#
# - Determines if script should run in verbose mode
# - Checks VERBOSE and var_verbose variables
# - Also returns true if not running in TTY (pipe/redirect scenario)
# - Used by msg_info() to decide between spinner and static output
# - Note: Non-TTY (pipe) scenarios are handled separately in msg_info()
# to allow spinner output to pass through pipes (e.g. lxc-attach | tee)
# ------------------------------------------------------------------------------
is_verbose_mode() {
local verbose="${VERBOSE:-${var_verbose:-no}}"
local tty_status
if [[ -t 2 ]]; then
tty_status="interactive"
else
tty_status="not-a-tty"
fi
[[ "$verbose" != "no" || ! -t 2 ]]
[[ "$verbose" != "no" ]]
}
# ------------------------------------------------------------------------------

View File

@@ -94,6 +94,29 @@ if ! declare -f explain_exit_code &>/dev/null; then
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
# --- Script Validation & Setup (103-123) ---
103) echo "Validation: Shell is not Bash" ;;
104) echo "Validation: Not running as root (or invoked via sudo)" ;;
105) echo "Validation: Proxmox VE version not supported" ;;
106) echo "Validation: Architecture not supported (ARM / PiMox)" ;;
107) echo "Validation: Kernel key parameters unreadable" ;;
108) echo "Validation: Kernel key limits exceeded" ;;
109) echo "Proxmox: No available container ID after max attempts" ;;
110) echo "Proxmox: Failed to apply default.vars" ;;
111) echo "Proxmox: App defaults file not available" ;;
112) echo "Proxmox: Invalid install menu option" ;;
113) echo "LXC: Under-provisioned — user aborted update" ;;
114) echo "LXC: Storage too low — user aborted update" ;;
115) echo "Download: install.func download failed or incomplete" ;;
116) echo "Proxmox: Default bridge vmbr0 not found" ;;
117) echo "LXC: Container did not reach running state" ;;
118) echo "LXC: No IP assigned to container after timeout" ;;
119) echo "Proxmox: No valid storage for rootdir content" ;;
120) echo "Proxmox: No valid storage for vztmpl content" ;;
121) echo "LXC: Container network not ready (no IP after retries)" ;;
122) echo "LXC: No internet connectivity — user declined to continue" ;;
123) echo "LXC: Local IP detection failed" ;;
124) echo "Command timed out (timeout command)" ;;
125) echo "Command failed to start (Docker daemon or execution error)" ;;
126) echo "Command invoked cannot execute (permission problem?)" ;;
@@ -155,6 +178,16 @@ if ! declare -f explain_exit_code &>/dev/null; then
224) echo "Proxmox: PBS storage is for backups only" ;;
225) echo "Proxmox: No template available for OS/Version" ;;
231) echo "Proxmox: LXC stack upgrade failed" ;;
# --- Tools & Addon Scripts (232-238) ---
232) echo "Tools: Wrong execution environment (run on PVE host, not inside LXC)" ;;
233) echo "Tools: Application not installed (update prerequisite missing)" ;;
234) echo "Tools: No LXC containers found or available" ;;
235) echo "Tools: Backup or restore operation failed" ;;
236) echo "Tools: Required hardware not detected" ;;
237) echo "Tools: Dependency package installation failed" ;;
238) echo "Tools: OS or distribution not supported for this addon" ;;
239) echo "npm/Node.js: Unexpected runtime error or dependency failure" ;;
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
245) echo "Node.js: Invalid command-line option" ;;
@@ -162,6 +195,14 @@ if ! declare -f explain_exit_code &>/dev/null; then
247) echo "Node.js: Fatal internal error" ;;
248) echo "Node.js: Invalid C++ addon / N-API failure" ;;
249) echo "npm/pnpm/yarn: Unknown fatal error" ;;
# --- Application Install/Update Errors (250-254) ---
250) echo "App: Download failed or version not determined" ;;
251) echo "App: File extraction failed (corrupt or incomplete archive)" ;;
252) echo "App: Required file or resource not found" ;;
253) echo "App: Data migration required — update aborted" ;;
254) echo "App: User declined prompt or input timed out" ;;
255) echo "DPKG: Fatal internal error" ;;
*) echo "Unknown error" ;;
esac
@@ -286,7 +327,9 @@ error_handler() {
echo -en "${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
fi
if read -t 60 -r response </dev/tty; then
# Read user response
local response=""
if read -t 60 -r response; then
if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then
echo ""
if declare -f msg_info >/dev/null 2>&1; then
@@ -365,10 +408,29 @@ _send_abort_telemetry() {
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
[[ -z "${RANDOM_UUID:-}" ]] && return 0
# Collect last 20 log lines for error diagnosis (best-effort)
# Collect last 200 log lines for error diagnosis (best-effort)
# Container context has no get_full_log(), so we gather as much as possible
local error_text=""
local logfile=""
if [[ -n "${INSTALL_LOG:-}" && -s "${INSTALL_LOG}" ]]; then
error_text=$(tail -n 20 "$INSTALL_LOG" 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\\/\\\\/g; s/"/\\"/g; s/\r//g' | tr '\n' '|' | sed 's/|$//' | tr -d '\000-\010\013\014\016-\037\177') || true
logfile="${INSTALL_LOG}"
elif [[ -n "${SILENT_LOGFILE:-}" && -s "${SILENT_LOGFILE}" ]]; then
logfile="${SILENT_LOGFILE}"
fi
if [[ -n "$logfile" ]]; then
error_text=$(tail -n 200 "$logfile" 2>/dev/null | sed 's/\x1b\[[0-9;]*[a-zA-Z]//g; s/\\/\\\\/g; s/"/\\"/g; s/\r//g' | tr '\n' '|' | sed 's/|$//' | head -c 16384 | tr -d '\000-\010\013\014\016-\037\177') || true
fi
# Prepend exit code explanation header (like build_error_string does on host)
local explanation=""
if declare -f explain_exit_code &>/dev/null; then
explanation=$(explain_exit_code "$exit_code" 2>/dev/null) || true
fi
if [[ -n "$explanation" && -n "$error_text" ]]; then
error_text="exit_code=${exit_code} | ${explanation}|---|${error_text}"
elif [[ -n "$explanation" && -z "$error_text" ]]; then
error_text="exit_code=${exit_code} | ${explanation}"
fi
# Calculate duration if start time is available
@@ -377,10 +439,17 @@ _send_abort_telemetry() {
duration=$(($(date +%s) - DIAGNOSTICS_START_TIME))
fi
# Categorize error if function is available (may not be in minimal container context)
local error_category=""
if declare -f categorize_error &>/dev/null; then
error_category=$(categorize_error "$exit_code" 2>/dev/null) || true
fi
# Build JSON payload with error context
local payload
payload="{\"random_id\":\"${RANDOM_UUID}\",\"execution_id\":\"${EXECUTION_ID:-${RANDOM_UUID}}\",\"type\":\"${TELEMETRY_TYPE:-lxc}\",\"nsapp\":\"${NSAPP:-${app:-unknown}}\",\"status\":\"failed\",\"exit_code\":${exit_code}"
[[ -n "$error_text" ]] && payload="${payload},\"error\":\"${error_text}\""
[[ -n "$error_category" ]] && payload="${payload},\"error_category\":\"${error_category}\""
[[ -n "$duration" ]] && payload="${payload},\"duration\":${duration}"
payload="${payload}}"

View File

@@ -126,7 +126,7 @@ setting_up_container() {
if [ "$(hostname -I)" = "" ]; then
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
echo -e "${NETWORK}Check Network Settings"
exit 1
exit 121
fi
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
systemctl disable -q --now systemd-networkd-wait-online.service
@@ -177,7 +177,7 @@ network_check() {
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
else
echo -e "${NETWORK}Check Network Settings"
exit 1
exit 122
fi
fi
@@ -242,12 +242,12 @@ EOF
local tools_content
tools_content=$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) || {
msg_error "Failed to download tools.func"
exit 6
exit 115
}
source /dev/stdin <<<"$tools_content"
if ! declare -f fetch_and_deploy_gh_release >/dev/null 2>&1; then
msg_error "tools.func loaded but incomplete — missing expected functions"
exit 6
exit 115
fi
}

File diff suppressed because it is too large Load Diff

View File

@@ -244,7 +244,7 @@ curl_handler() {
if [[ -z "$url" ]]; then
msg_error "no valid url or option entered for curl_handler"
exit 1
exit 64
fi
$STD msg_info "Fetching: $url"
@@ -273,7 +273,7 @@ curl_handler() {
rm -f /tmp/curl_error.log
fi
__curl_err_handler "$exit_code" "$url" "$curl_stderr"
exit 1 # hard exit if exit_code is not 0
exit "$exit_code"
fi
$STD printf "\r\033[K${INFO}${YW}Retry $attempt/$max_retries in ${delay}s...${CL}" >&2
@@ -316,7 +316,7 @@ __curl_err_handler() {
esac
[[ -n "$curl_msg" ]] && printf "%s\n" "$curl_msg" >&2
exit 1
exit "$exit_code"
}
# ------------------------------------------------------------------------------
@@ -331,7 +331,7 @@ shell_check() {
msg_error "Your default shell is currently not set to Bash. To use these scripts, please switch to the Bash shell."
echo -e "\nExiting..."
sleep 2
exit
exit 103
fi
}
@@ -352,11 +352,11 @@ clear_line() {
#
# - Determines if script should run in verbose mode
# - Checks VERBOSE and var_verbose variables
# - Also returns true if not running in TTY (pipe/redirect scenario)
# - Note: Non-TTY (pipe) scenarios are handled separately in msg_info()
# ------------------------------------------------------------------------------
is_verbose_mode() {
local verbose="${VERBOSE:-${var_verbose:-no}}"
[[ "$verbose" != "no" || ! -t 2 ]]
[[ "$verbose" != "no" ]]
}
### dev spinner ###
@@ -552,7 +552,7 @@ check_root() {
msg_error "Please run this script as root."
echo -e "\nExiting..."
sleep 2
exit
exit 104
fi
}
@@ -562,7 +562,7 @@ pve_check() {
echo -e "Requires Proxmox Virtual Environment Version 8.1 - 8.4 or 9.0 - 9.1."
echo -e "Exiting..."
sleep 2
exit
exit 105
fi
}
@@ -572,21 +572,21 @@ arch_check() {
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
echo -e "Exiting..."
sleep 2
exit
exit 106
fi
}
exit_script() {
clear
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
exit
exit 0
}
check_hostname_conflict() {
local hostname="$1"
if qm list | awk '{print $2}' | grep -qx "$hostname"; then
msg_error "Hostname $hostname already in use by another VM."
exit 1
exit 206
fi
}

View File

@@ -73,7 +73,7 @@ fi
DISTRO=$(pct exec "$CTID" -- cat /etc/os-release | grep -w "ID" | cut -d'=' -f2 | tr -d '"')
if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then
msg "\e[1;31m Error: This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting...\e[0m"
exit 1
exit 238
fi
CTID_CONFIG_PATH=/etc/pve/lxc/${CTID}.conf

View File

@@ -32,7 +32,7 @@ header_info
if ! command -v pveversion &>/dev/null; then
msg_error "This script must be run on the Proxmox VE host (not inside an LXC container)"
exit 1
exit 232
fi
while true; do
@@ -64,7 +64,7 @@ while [[ -z "${CTID}" ]]; do
CTID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Containers on $NODE" --radiolist \
"\nSelect a container to add Tailscale to:\n" \
16 $((MSG_MAX_LENGTH + 23)) 6 \
"${CTID_MENU[@]}" 3>&1 1>&2 2>&3) || exit 1
"${CTID_MENU[@]}" 3>&1 1>&2 2>&3) || exit 0
done
CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"

View File

@@ -69,7 +69,7 @@ elif [[ -f "/etc/debian_version" ]]; then
SERVICE_PATH="/etc/systemd/system/adguardhome-sync.service"
else
msg_error "Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -312,7 +312,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -87,11 +87,11 @@ function update() {
function check_docker() {
if ! command -v docker &>/dev/null; then
msg_error "Docker is not installed. This script requires an existing Docker LXC. Exiting."
exit 1
exit 10
fi
if ! docker compose version &>/dev/null; then
msg_error "Docker Compose plugin is not available. Please install it before running this script. Exiting."
exit 1
exit 10
fi
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
}
@@ -171,7 +171,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

215
tools/addon/coolify.sh Normal file
View File

@@ -0,0 +1,215 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://coolify.io/ | Github: https://github.com/coollabsio/coolify
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
if [[ -f /etc/alpine-release ]]; then
apk update >/dev/null 2>&1
apk add --no-cache curl >/dev/null 2>&1
else
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Coolify"
APP_TYPE="addon"
INSTALL_PATH="/data/coolify"
DEFAULT_PORT=8000
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
if command -v docker &>/dev/null; then
msg_info "Stopping and removing Docker containers"
cd /data/coolify/source 2>/dev/null && docker compose down --remove-orphans 2>/dev/null || true
$STD docker stop $(docker ps -aq) 2>/dev/null || true
$STD docker rm $(docker ps -aq) 2>/dev/null || true
$STD docker network prune -f 2>/dev/null || true
msg_ok "Stopped and removed Docker containers"
fi
rm -rf "$INSTALL_PATH"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
msg_info "Updating ${APP}"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Updated ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# PROXMOX HOST CHECK
# ==============================================================================
function check_proxmox_host() {
if command -v pveversion &>/dev/null; then
msg_error "Running on the Proxmox host is NOT recommended!"
msg_error "This should be executed inside an LXC container."
echo ""
echo -n "${TAB}Continue anyway? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Aborted. Please run this inside an LXC container."
exit 0
fi
msg_warn "Proceeding on Proxmox host at your own risk!"
fi
}
# ==============================================================================
# CHECK / INSTALL DOCKER
# ==============================================================================
function check_or_install_docker() {
if command -v docker &>/dev/null; then
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
if docker compose version &>/dev/null; then
msg_ok "Docker Compose is available"
else
msg_error "Docker Compose plugin is not available. Please install it."
exit 10
fi
return
fi
msg_warn "Docker is not installed."
echo -n "${TAB}Install Docker now? (y/N): "
read -r install_docker_prompt
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_error "Docker is required for ${APP}. Exiting."
exit 10
fi
msg_info "Installing Docker"
if [[ -f /etc/alpine-release ]]; then
$STD apk add docker docker-cli-compose
$STD rc-service docker start
$STD rc-update add docker default
else
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
$STD sh <(curl -fsSL https://get.docker.com)
fi
msg_ok "Installed Docker"
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_or_install_docker
msg_info "Installing dependencies"
if [[ -f /etc/alpine-release ]]; then
$STD apk add --no-cache git openssl
else
$STD apt-get update
$STD apt-get install -y git openssl
fi
msg_ok "Installed dependencies"
msg_warn "WARNING: This will run an external installer from https://coolify.io/"
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "Review: https://cdn.coollabs.io/coolify/install.sh"
echo ""
echo -n "${TAB}Do you want to continue? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Installation cancelled. Exiting."
exit 0
fi
msg_info "Installing ${APP} (this installs Docker and pulls containers)"
$STD bash <(curl -fsSL https://cdn.coollabs.io/coolify/install.sh)
msg_ok "Installed ${APP}"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
header_info
check_proxmox_host
get_lxc_ip
# Check if already installed
if [[ -d "$INSTALL_PATH" ]]; 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} - Coolify (via external installer)"
echo -e "${TAB} - Docker (if not already installed)"
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

View File

@@ -49,7 +49,7 @@ elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
SERVICE_PATH="/etc/systemd/system/copyparty.service"
else
msg_error "Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -318,7 +318,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -51,7 +51,7 @@ EOF
# ==============================================================================
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
exit 238
fi
# ==============================================================================
@@ -183,7 +183,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

209
tools/addon/dockge.sh Normal file
View File

@@ -0,0 +1,209 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: tteck (tteckster) | Addon: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://dockge.kuma.pet/ | Github: https://github.com/louislam/dockge
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
if [[ -f /etc/alpine-release ]]; then
apk update >/dev/null 2>&1
apk add --no-cache curl >/dev/null 2>&1
else
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Dockge"
APP_TYPE="addon"
INSTALL_PATH="/opt/dockge"
STACKS_PATH="/opt/stacks"
COMPOSE_FILE="${INSTALL_PATH}/compose.yaml"
DEFAULT_PORT=5001
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
if [[ -f "$COMPOSE_FILE" ]]; then
msg_info "Stopping and removing Docker containers"
cd "$INSTALL_PATH"
$STD docker compose down --remove-orphans
msg_ok "Stopped and removed Docker containers"
fi
rm -rf "$INSTALL_PATH"
msg_ok "${APP} has been uninstalled"
msg_warn "Stacks directory ${STACKS_PATH} was NOT removed. Delete manually if no longer needed."
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
msg_info "Pulling latest ${APP} image"
cd "$INSTALL_PATH"
$STD docker compose pull
msg_ok "Pulled latest image"
msg_info "Restarting ${APP}"
$STD docker compose up -d --remove-orphans
msg_ok "Restarted ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# PROXMOX HOST CHECK
# ==============================================================================
function check_proxmox_host() {
if command -v pveversion &>/dev/null; then
msg_error "Running on the Proxmox host is NOT recommended!"
msg_error "This should be executed inside an LXC container."
echo ""
echo -n "${TAB}Continue anyway? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Aborted. Please run this inside an LXC container."
exit 0
fi
msg_warn "Proceeding on Proxmox host at your own risk!"
fi
}
# ==============================================================================
# CHECK / INSTALL DOCKER
# ==============================================================================
function check_or_install_docker() {
if command -v docker &>/dev/null; then
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
if docker compose version &>/dev/null; then
msg_ok "Docker Compose is available"
else
msg_error "Docker Compose plugin is not available. Please install it."
exit 10
fi
return
fi
msg_warn "Docker is not installed."
echo -n "${TAB}Install Docker now? (y/N): "
read -r install_docker_prompt
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_error "Docker is required for ${APP}. Exiting."
exit 10
fi
msg_info "Installing Docker"
if [[ -f /etc/alpine-release ]]; then
$STD apk add docker docker-cli-compose
$STD rc-service docker start
$STD rc-update add docker default
else
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
$STD sh <(curl -fsSL https://get.docker.com)
fi
msg_ok "Installed Docker"
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_or_install_docker
msg_info "Creating install directories"
mkdir -p "$INSTALL_PATH" "$STACKS_PATH"
msg_ok "Created ${INSTALL_PATH} and ${STACKS_PATH}"
msg_info "Downloading Docker Compose file"
curl -fsSL "https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml" -o "$COMPOSE_FILE"
msg_ok "Downloaded Docker Compose file"
msg_info "Starting ${APP}"
cd "$INSTALL_PATH"
$STD docker compose up -d
msg_ok "Started ${APP}"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -f "$COMPOSE_FILE" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
header_info
check_proxmox_host
get_lxc_ip
# Check if already installed
if [[ -f "$COMPOSE_FILE" ]]; then
msg_warn "${APP} is already installed."
echo ""
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
fi
echo -n "${TAB}Update ${APP}? (y/N): "
read -r update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
update
exit 0
fi
msg_warn "No action selected. Exiting."
exit 0
fi
# Fresh installation
msg_warn "${APP} is not installed."
echo ""
echo -e "${TAB}${INFO} This will install:"
echo -e "${TAB} - Dockge (via Docker Compose)"
echo ""
echo -n "${TAB}Install ${APP}? (y/N): "
read -r install_prompt
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
install
else
msg_warn "Installation cancelled. Exiting."
exit 0
fi

214
tools/addon/dokploy.sh Normal file
View File

@@ -0,0 +1,214 @@
#!/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://dokploy.com/ | Github: https://github.com/Dokploy/dokploy
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
if [[ -f /etc/alpine-release ]]; then
apk update >/dev/null 2>&1
apk add --no-cache curl >/dev/null 2>&1
else
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Dokploy"
APP_TYPE="addon"
INSTALL_PATH="/etc/dokploy"
DEFAULT_PORT=3000
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
if command -v docker &>/dev/null; then
msg_info "Stopping and removing Docker containers"
$STD docker stop $(docker ps -aq) 2>/dev/null || true
$STD docker rm $(docker ps -aq) 2>/dev/null || true
$STD docker network prune -f 2>/dev/null || true
msg_ok "Stopped and removed Docker containers"
fi
rm -rf "$INSTALL_PATH"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
msg_info "Updating ${APP}"
$STD curl -sSL https://dokploy.com/install.sh | bash -s update
msg_ok "Updated ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# PROXMOX HOST CHECK
# ==============================================================================
function check_proxmox_host() {
if command -v pveversion &>/dev/null; then
msg_error "Running on the Proxmox host is NOT recommended!"
msg_error "This should be executed inside an LXC container."
echo ""
echo -n "${TAB}Continue anyway? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Aborted. Please run this inside an LXC container."
exit 0
fi
msg_warn "Proceeding on Proxmox host at your own risk!"
fi
}
# ==============================================================================
# CHECK / INSTALL DOCKER
# ==============================================================================
function check_or_install_docker() {
if command -v docker &>/dev/null; then
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
if docker compose version &>/dev/null; then
msg_ok "Docker Compose is available"
else
msg_error "Docker Compose plugin is not available. Please install it."
exit 10
fi
return
fi
msg_warn "Docker is not installed."
echo -n "${TAB}Install Docker now? (y/N): "
read -r install_docker_prompt
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_error "Docker is required for ${APP}. Exiting."
exit 10
fi
msg_info "Installing Docker"
if [[ -f /etc/alpine-release ]]; then
$STD apk add docker docker-cli-compose
$STD rc-service docker start
$STD rc-update add docker default
else
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
$STD sh <(curl -fsSL https://get.docker.com)
fi
msg_ok "Installed Docker"
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_or_install_docker
msg_info "Installing dependencies"
if [[ -f /etc/alpine-release ]]; then
$STD apk add --no-cache git openssl
else
$STD apt-get update
$STD apt-get install -y git openssl redis
fi
msg_ok "Installed dependencies"
msg_warn "WARNING: This will run an external installer from https://dokploy.com/"
msg_warn "The following code is NOT maintained or audited by our repository."
echo ""
echo -n "${TAB}Do you want to continue? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Installation cancelled. Exiting."
exit 0
fi
msg_info "Installing ${APP} (this installs Docker and pulls containers)"
$STD bash <(curl -sSL https://dokploy.com/install.sh)
msg_ok "Installed ${APP}"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
header_info
check_proxmox_host
get_lxc_ip
# Check if already installed
if [[ -d "$INSTALL_PATH" ]]; 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} - Dokploy (via external installer)"
echo -e "${TAB} - Docker (if not already installed)"
echo -e "${TAB} - Redis"
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

View File

@@ -54,7 +54,7 @@ elif [[ -f "/etc/debian_version" ]]; then
PKG_MANAGER="apt-get install -y"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
header_info

View File

@@ -52,7 +52,7 @@ elif [[ -f "/etc/debian_version" ]]; then
PKG_MANAGER="apt-get install -y"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
header_info

View File

@@ -93,7 +93,7 @@ EOF
update_glances_debian() {
if [[ ! -d /opt/glances/.venv ]]; then
msg_error "$APP is not installed"
exit 1
exit 233
fi
msg_info "Updating $APP"
cd /opt/glances
@@ -160,7 +160,7 @@ EOF
update_glances_alpine() {
if [[ ! -d /opt/glances/.venv ]]; then
msg_error "$APP is not installed"
exit 1
exit 233
fi
msg_info "Updating $APP"
cd /opt/glances

View File

@@ -52,13 +52,13 @@ EOF
# ==============================================================================
if [[ -f "/etc/alpine-release" ]]; then
msg_error "Alpine is not supported for ${APP}. Use Debian."
exit 1
exit 238
elif [[ -f "/etc/debian_version" ]]; then
OS="Debian"
SERVICE_PATH="/etc/systemd/system/immich-proxy.service"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -231,7 +231,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -52,13 +52,13 @@ EOF
# ==============================================================================
if [[ -f "/etc/alpine-release" ]]; then
msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
exit 1
exit 238
elif [[ -f "/etc/debian_version" ]]; then
OS="Debian"
SERVICE_PATH="/etc/systemd/system/jellystat.service"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -326,7 +326,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

293
tools/addon/komodo.sh Normal file
View File

@@ -0,0 +1,293 @@
#!/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://komo.do/ | Github: https://github.com/mbecker20/komodo
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 || apk update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 || apk add --no-cache curl >/dev/null 2>&1
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Komodo"
APP_TYPE="addon"
INSTALL_PATH="/opt/komodo"
COMPOSE_ENV="${INSTALL_PATH}/compose.env"
DEFAULT_PORT=9120
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# HELPERS
# ==============================================================================
function find_compose_file() {
COMPOSE_FILE=$(find "$INSTALL_PATH" -maxdepth 1 -type f -name '*.compose.yaml' ! -name 'compose.env' | head -n1)
if [[ -z "${COMPOSE_FILE:-}" ]]; then
msg_error "No valid compose file found in ${INSTALL_PATH}!"
exit 233
fi
COMPOSE_BASENAME=$(basename "$COMPOSE_FILE")
}
function check_legacy_db() {
if [[ "$COMPOSE_BASENAME" == "sqlite.compose.yaml" || "$COMPOSE_BASENAME" == "postgres.compose.yaml" ]]; then
msg_error "Detected outdated Komodo setup using SQLite or PostgreSQL (FerretDB v1)."
echo -e "${YW}This configuration is no longer supported since Komodo v1.18.0.${CL}"
echo -e "${YW}Please follow the migration guide:${CL}"
echo -e "${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/5689${CL}\n"
exit 238
fi
}
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
find_compose_file
msg_info "Stopping and removing Docker containers"
cd "$INSTALL_PATH"
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file "$COMPOSE_ENV" down --volumes --remove-orphans
msg_ok "Stopped and removed Docker containers"
rm -rf "$INSTALL_PATH"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
find_compose_file
check_legacy_db
msg_info "Updating ${APP}"
BACKUP_FILE="${INSTALL_PATH}/${COMPOSE_BASENAME}.bak_$(date +%Y%m%d_%H%M%S)"
cp "$COMPOSE_FILE" "$BACKUP_FILE" || {
msg_error "Failed to create backup of ${COMPOSE_BASENAME}!"
exit 235
}
GITHUB_URL="https://raw.githubusercontent.com/moghtech/komodo/main/compose/${COMPOSE_BASENAME}"
if ! curl -fsSL "$GITHUB_URL" -o "$COMPOSE_FILE"; then
msg_error "Failed to download ${COMPOSE_BASENAME} from GitHub!"
mv "$BACKUP_FILE" "$COMPOSE_FILE"
exit 115
fi
if ! grep -qxF 'COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' "$COMPOSE_ENV"; then
sed -i '/^COMPOSE_KOMODO_IMAGE_TAG=latest$/a COMPOSE_KOMODO_BACKUPS_PATH=/etc/komodo/backups' "$COMPOSE_ENV"
fi
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file "$COMPOSE_ENV" pull
$STD docker compose -p komodo -f "$COMPOSE_FILE" --env-file "$COMPOSE_ENV" up -d
msg_ok "Updated ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# PROXMOX HOST CHECK
# ==============================================================================
function check_proxmox_host() {
if command -v pveversion &>/dev/null; then
msg_error "Running on the Proxmox host is NOT recommended!"
msg_error "This should be executed inside an LXC container."
echo ""
echo -n "${TAB}Continue anyway? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Aborted. Please run this inside an LXC container."
exit 0
fi
msg_warn "Proceeding on Proxmox host at your own risk!"
fi
}
# ==============================================================================
# CHECK / INSTALL DOCKER
# ==============================================================================
function check_or_install_docker() {
if command -v docker &>/dev/null; then
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
if docker compose version &>/dev/null; then
msg_ok "Docker Compose is available"
else
msg_error "Docker Compose plugin is not available. Please install it."
exit 10
fi
return
fi
msg_warn "Docker is not installed."
echo -n "${TAB}Install Docker now? (y/N): "
read -r install_docker_prompt
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_error "Docker is required for ${APP}. Exiting."
exit 10
fi
msg_info "Installing Docker"
if [[ -f /etc/alpine-release ]]; then
$STD apk add docker docker-cli-compose
$STD rc-service docker start
$STD rc-update add docker default
else
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
$STD sh <(curl -fsSL https://get.docker.com)
fi
msg_ok "Installed Docker"
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_or_install_docker
echo -e "${TAB}Choose the database for Komodo:"
echo -e "${TAB} 1) MongoDB (recommended)"
echo -e "${TAB} 2) FerretDB"
echo -n "${TAB}Enter your choice (default: 1): "
read -r DB_CHOICE
DB_CHOICE=${DB_CHOICE:-1}
case $DB_CHOICE in
1) DB_COMPOSE_FILE="mongo.compose.yaml" ;;
2) DB_COMPOSE_FILE="ferretdb.compose.yaml" ;;
*)
msg_warn "Invalid choice. Defaulting to MongoDB."
DB_COMPOSE_FILE="mongo.compose.yaml"
;;
esac
msg_info "Creating install directory"
mkdir -p "$INSTALL_PATH"
msg_ok "Created ${INSTALL_PATH}"
msg_info "Downloading Docker Compose file"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/$DB_COMPOSE_FILE" -o "${INSTALL_PATH}/${DB_COMPOSE_FILE}"
msg_ok "Downloaded ${DB_COMPOSE_FILE}"
msg_info "Configuring environment"
curl -fsSL "https://raw.githubusercontent.com/moghtech/komodo/main/compose/compose.env" -o "$COMPOSE_ENV"
DB_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=')
ADMIN_PASSWORD=$(openssl rand -base64 8 | tr -d '/+=')
PASSKEY=$(openssl rand -base64 24 | tr -d '/+=')
WEBHOOK_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
JWT_SECRET=$(openssl rand -base64 24 | tr -d '/+=')
sed -i "s/^KOMODO_DB_USERNAME=.*/KOMODO_DB_USERNAME=komodo_admin/" "$COMPOSE_ENV"
sed -i "s/^KOMODO_DB_PASSWORD=.*/KOMODO_DB_PASSWORD=${DB_PASSWORD}/" "$COMPOSE_ENV"
sed -i "s/^KOMODO_INIT_ADMIN_PASSWORD=changeme/KOMODO_INIT_ADMIN_PASSWORD=${ADMIN_PASSWORD}/" "$COMPOSE_ENV"
sed -i "s/^KOMODO_PASSKEY=.*/KOMODO_PASSKEY=${PASSKEY}/" "$COMPOSE_ENV"
sed -i "s/^KOMODO_WEBHOOK_SECRET=.*/KOMODO_WEBHOOK_SECRET=${WEBHOOK_SECRET}/" "$COMPOSE_ENV"
sed -i "s/^KOMODO_JWT_SECRET=.*/KOMODO_JWT_SECRET=${JWT_SECRET}/" "$COMPOSE_ENV"
msg_ok "Configured environment"
msg_info "Starting ${APP}"
cd "$INSTALL_PATH"
$STD docker compose -p komodo -f "${INSTALL_PATH}/${DB_COMPOSE_FILE}" --env-file "$COMPOSE_ENV" up -d
msg_ok "Started ${APP}"
{
echo "Komodo Credentials"
echo ""
echo "Admin User : admin"
echo "Admin Password: $ADMIN_PASSWORD"
} >>~/komodo.creds
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
echo ""
echo -e " Komodo Credentials"
echo -e " =================="
echo -e " User : admin"
echo -e " Password: ${ADMIN_PASSWORD}"
echo ""
msg_info "Credentials saved to ~/komodo.creds"
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
COMPOSE_FILE=""
COMPOSE_BASENAME=""
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
header_info
check_proxmox_host
get_lxc_ip
# Declare variables used by find_compose_file
COMPOSE_FILE=""
COMPOSE_BASENAME=""
# Check if already installed
if [[ -d "$INSTALL_PATH" ]]; 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} - Komodo (via Docker Compose)"
echo -e "${TAB} - MongoDB or FerretDB (your choice)"
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

View File

@@ -58,7 +58,7 @@ pve_check() {
if ((MINOR < 0 || MINOR > 9)); then
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported: Proxmox VE version 8.0 8.9"
exit 1
exit 105
fi
return 0
fi
@@ -69,7 +69,7 @@ pve_check() {
if ((MINOR < 0 || MINOR > 1)); then
msg_error "This version of Proxmox VE is not yet supported."
msg_error "Supported: Proxmox VE version 9.09.1.x"
exit 1
exit 105
fi
return 0
fi
@@ -77,19 +77,19 @@ pve_check() {
# All other unsupported versions
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported versions: Proxmox VE 8.0 8.9 or 9.09.1.x"
exit 1
exit 105
}
detect_codename() {
source /etc/os-release
if [[ "$ID" != "debian" ]]; then
msg_error "Unsupported base OS: $ID (only Proxmox VE / Debian supported)."
exit 1
exit 238
fi
CODENAME="${VERSION_CODENAME:-}"
if [[ -z "$CODENAME" ]]; then
msg_error "Could not detect Debian codename."
exit 1
exit 71
fi
echo "$CODENAME"
}
@@ -124,7 +124,7 @@ install() {
PKG=$(get_latest_repo_pkg "$REPO_URL")
if [[ -z "$PKG" ]]; then
msg_error "Could not find netdata-repo package for Debian $CODENAME"
exit 1
exit 237
fi
curl -fsSL "${REPO_URL}${PKG}" -o "$PKG"
$STD dpkg -i "$PKG"

View File

@@ -36,7 +36,7 @@ SERVICE_PATH="/etc/systemd/system/nextcloud-exporter.service"
# ==============================================================================
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
exit 238
fi
# ==============================================================================
@@ -170,7 +170,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "Nextcloud-Exporter is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -52,7 +52,7 @@ elif [[ -f "/etc/debian_version" ]]; then
INSTALL_DIR="$INSTALL_DIR_DEBIAN"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
header_info
@@ -72,7 +72,7 @@ function check_internet() {
msg_ok "Internet connectivity OK"
else
msg_error "Internet connectivity or GitHub unreachable (Status $HTTP_CODE). Exiting."
exit 1
exit 115
fi
}
@@ -105,7 +105,7 @@ function install_php_and_modules() {
msg_info "Installing missing PHP packages: ${MISSING_PACKAGES[*]}"
if ! apt-get update &>/dev/null || ! apt-get install -y "${MISSING_PACKAGES[@]}" &>/dev/null; then
msg_error "Failed to install required PHP modules. Exiting."
exit 1
exit 237
fi
msg_ok "Installed missing PHP packages"
else
@@ -132,7 +132,7 @@ function install_phpmyadmin() {
msg_info "Downloading ${TARBALL_URL}"
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
msg_error "Download failed: $TARBALL_URL"
exit 1
exit 115
fi
mkdir -p "$INSTALL_DIR"
@@ -188,7 +188,7 @@ EOF
msg_ok "Started PHP-FPM service: $PHP_FPM_SERVICE"
else
msg_error "Failed to start PHP-FPM service: $PHP_FPM_SERVICE"
exit 1
exit 150
fi
$STD rc-service lighttpd start
@@ -237,7 +237,7 @@ function update_phpmyadmin() {
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
msg_error "Download failed: $TARBALL_URL"
exit 1
exit 115
fi
BACKUP_DIR="/tmp/phpmyadmin-backup-$(date +%Y%m%d-%H%M%S)"
@@ -280,7 +280,7 @@ if is_phpmyadmin_installed; then
;;
*)
echo -e "${YW}⚠️ Invalid input. Exiting.${CL}"
exit 1
exit 112
;;
esac
else

View File

@@ -41,7 +41,7 @@ elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
SERVICE_PATH="/etc/systemd/system/pihole-exporter.service"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -207,7 +207,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "Pihole-Exporter is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -32,7 +32,7 @@ AUTH_TOKEN_FILE="/etc/prometheus-paperless-ngx-exporter/paperless_auth_token_fil
# ==============================================================================
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
exit 238
fi
# ==============================================================================
@@ -144,7 +144,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "Prometheus-Paperless-NGX-Exporter is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

View File

@@ -41,7 +41,7 @@ elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
SERVICE_PATH="/etc/systemd/system/qbittorrent-exporter.service"
else
echo -e "${CROSS} Unsupported OS detected. Exiting."
exit 1
exit 238
fi
# ==============================================================================
@@ -200,7 +200,7 @@ if [[ "${type:-}" == "update" ]]; then
update
else
msg_error "qBittorrent-Exporter is not installed. Nothing to update."
exit 1
exit 233
fi
exit 0
fi

223
tools/addon/runtipi.sh Normal file
View File

@@ -0,0 +1,223 @@
#!/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://runtipi.io/ | Github: https://github.com/runtipi/runtipi
if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
if [[ -f /etc/alpine-release ]]; then
apk update >/dev/null 2>&1
apk add --no-cache curl >/dev/null 2>&1
else
apt-get update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1
fi
fi
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Runtipi"
APP_TYPE="addon"
INSTALL_PATH="/opt/runtipi"
DEFAULT_PORT=80
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# PROXMOX HOST CHECK
# ==============================================================================
function check_proxmox_host() {
if command -v pveversion &>/dev/null; then
msg_error "Running on the Proxmox host is NOT recommended!"
msg_error "This should be executed inside an LXC container."
echo ""
echo -n "${TAB}Continue anyway? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Aborted. Please run this inside an LXC container."
exit 0
fi
msg_warn "Proceeding on Proxmox host at your own risk!"
fi
}
# ==============================================================================
# CHECK / INSTALL DOCKER
# ==============================================================================
function check_or_install_docker() {
if command -v docker &>/dev/null; then
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
if docker compose version &>/dev/null; then
msg_ok "Docker Compose is available"
else
msg_error "Docker Compose plugin is not available. Please install it."
exit 10
fi
return
fi
msg_warn "Docker is not installed."
echo -n "${TAB}Install Docker now? (y/N): "
read -r install_docker_prompt
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_error "Docker is required for ${APP}. Exiting."
exit 10
fi
msg_info "Installing Docker"
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
$STD sh <(curl -fsSL https://get.docker.com)
msg_ok "Installed Docker"
}
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
if [[ -f "${INSTALL_PATH}/runtipi-cli" ]]; then
msg_info "Stopping ${APP}"
cd "$INSTALL_PATH"
$STD ./runtipi-cli stop 2>/dev/null || true
msg_ok "Stopped ${APP}"
fi
if command -v docker &>/dev/null; then
msg_info "Removing Docker containers"
cd "$INSTALL_PATH" 2>/dev/null && $STD docker compose down --remove-orphans 2>/dev/null || true
msg_ok "Removed Docker containers"
fi
rm -rf "$INSTALL_PATH"
msg_ok "${APP} has been uninstalled"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
msg_info "Updating ${APP}"
cd "$INSTALL_PATH"
$STD ./runtipi-cli update latest
msg_ok "Updated ${APP}"
msg_ok "Updated successfully"
exit
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_or_install_docker
msg_info "Installing dependencies"
$STD apt-get update
$STD apt-get install -y openssl
msg_ok "Installed dependencies"
msg_warn "WARNING: This will run an external installer from https://runtipi.io/"
msg_warn "The following code is NOT maintained or audited by our repository."
msg_warn "Review: https://raw.githubusercontent.com/runtipi/runtipi/master/scripts/install.sh"
echo ""
echo -n "${TAB}Do you want to continue? (y/N): "
read -r confirm
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
msg_warn "Installation cancelled. Exiting."
exit 0
fi
msg_info "Installing ${APP} (this pulls Docker containers)"
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
[[ ! -f "$DOCKER_CONFIG_PATH" ]] && echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
cd /opt
curl -fsSL "https://raw.githubusercontent.com/runtipi/runtipi/master/scripts/install.sh" -o "install.sh"
chmod +x install.sh
$STD ./install.sh
chmod 666 /opt/runtipi/state/settings.json 2>/dev/null || true
rm -f /opt/install.sh
msg_ok "Installed ${APP}"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -d "$INSTALL_PATH" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 233
fi
exit 0
fi
if [[ -f /etc/alpine-release ]]; then
msg_error "${APP} does not support Alpine Linux. Please use a Debian or Ubuntu based LXC."
exit 238
fi
header_info
check_proxmox_host
get_lxc_ip
# Check if already installed
if [[ -d "$INSTALL_PATH" ]]; 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} - Runtipi (via external installer)"
echo -e "${TAB} - Docker (if not already installed)"
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/coolify Normal file
View File

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

6
tools/headers/dockge Normal file
View File

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

6
tools/headers/dokploy Normal file
View File

@@ -0,0 +1,6 @@
____ __ __
/ __ \____ / /______ / /___ __ __
/ / / / __ \/ //_/ __ \/ / __ \/ / / /
/ /_/ / /_/ / ,< / /_/ / / /_/ / /_/ /
/_____/\____/_/|_/ .___/_/\____/\__, /
/_/ /____/

6
tools/headers/komodo Normal file
View File

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

6
tools/headers/runtipi Normal file
View File

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

View File

@@ -62,7 +62,7 @@ function msg_error() {
}
if [ -z "$(ls -A /var/lib/docker/volumes/hass_config/_data/backups/)" ]; then
msg_error "No backups found! \n"
exit 1
exit 235
fi
DIR=/var/lib/docker/volumes/hass_config/_data/restore
if [ -d "$DIR" ]; then

View File

@@ -62,7 +62,7 @@ function msg_error() {
}
if [ -z "$(ls -A /root/.homeassistant/backups/)" ]; then
msg_error "No backups found! \n"
exit 1
exit 235
fi
DIR=/root/.homeassistant/restore
if [ -d "$DIR" ]; then

View File

@@ -39,7 +39,7 @@ ROOT_FS=$(df -Th "/" | awk 'NR==2 {print $2}')
if [ "$ROOT_FS" != "ext4" ]; then
whiptail --backtitle "Proxmox VE Helper Scripts" \
--title "Warning" \
--yesno "Root filesystem is not ext4 ($ROOT_FS).\nContinue anyway?" 12 80 || exit 1
--yesno "Root filesystem is not ext4 ($ROOT_FS).\nContinue anyway?" 12 80 || exit 0
fi
NODE=$(hostname)

View File

@@ -57,7 +57,7 @@ done
if [ ${#kernels_to_remove[@]} -eq 0 ]; then
echo -e "${RD}No valid selection made. Exiting.${CL}"
exit 1
exit 0
fi
# Confirm removal
@@ -66,7 +66,7 @@ printf "%s\n" "${kernels_to_remove[@]}"
read -rp "Proceed with removal? (y/n): " confirm
if [[ "$confirm" != "y" ]]; then
echo -e "${RD}Aborted.${CL}"
exit 1
exit 0
fi
# Remove kernels

View File

@@ -51,7 +51,7 @@ containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}')
if [ -z "$containers" ]; then
whiptail --title "LXC Container Delete" --msgbox "No LXC containers available!" 10 60
exit 1
exit 234
fi
menu_items=("ALL" "Delete ALL containers" "OFF") # Add as first option
@@ -72,7 +72,7 @@ CHOICES=$(whiptail --title "LXC Container Delete" \
if [ -z "$CHOICES" ]; then
whiptail --title "LXC Container Delete" \
--msgbox "No containers selected!" 10 60
exit 1
exit 0
fi
read -p "Delete containers manually or automatically? (Default: manual) m/a: " DELETE_MODE

View File

@@ -47,7 +47,7 @@ function msg_warn() { echo -e "${WARN} ${YWB}${1}"; }
# Check for root privileges
if [ "$(id -u)" -ne 0 ]; then
msg_error "Error: This script must be run as root."
exit 1
exit 104
fi
if ! command -v ethtool >/dev/null 2>&1; then
@@ -55,7 +55,7 @@ if ! command -v ethtool >/dev/null 2>&1; then
apt-get update &>/dev/null
apt-get install -y ethtool &>/dev/null || {
msg_error "Failed to install ethtool. Exiting."
exit 1
exit 237
}
msg_ok "ethtool installed successfully"
fi
@@ -86,7 +86,7 @@ done
if [ ${#INTERFACES[@]} -eq 0 ]; then
whiptail --title "Error" --msgbox "No Intel e1000e or e1000 network interfaces found!" 10 60
msg_error "No Intel e1000e or e1000 network interfaces found! Exiting."
exit 1
exit 236
fi
msg_ok "Found ${BL}$COUNT${GN} Intel e1000e/e1000 interfaces"

Some files were not shown because too many files have changed in this diff Show More