Compare commits

...

92 Commits

Author SHA1 Message Date
community-scripts-pr-app[bot]
9256afda54 Update CHANGELOG.md (#10763)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-13 00:13:45 +00:00
community-scripts-pr-app[bot]
7d4b9316a2 Update versions.json (#10762)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-13 01:13:21 +01:00
community-scripts-pr-app[bot]
36743247f0 Update CHANGELOG.md (#10755)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 19:40:03 +00:00
community-scripts-pr-app[bot]
863876c3a2 Update CHANGELOG.md (#10754)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 19:39:42 +00:00
Christoph Niemann
50954ff560 Update influxdb-install.sh (#10753)
fix if/elif/else
2026-01-12 20:39:20 +01:00
community-scripts-pr-app[bot]
679c9cbb11 Update CHANGELOG.md (#10752)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 17:57:04 +00:00
Victor
b4c16ef05d Add setup for influxdb v3 (#10736) 2026-01-12 18:56:42 +01:00
CanbiZ
56e0783385 Show container ID warning only for user-specified IDs
The warning about a container ID being in use is now only shown if the user manually specified an ID, not when the ID is auto-assigned. This reduces unnecessary warnings during automated container creation.
2026-01-12 18:52:08 +01:00
CanbiZ
305a2ef449 Validate storage space only if container storage set
Storage space validation now occurs only when CONTAINER_STORAGE is defined, preventing premature validation before storage selection in certain modes. This avoids unnecessary errors and aligns validation with actual container creation logic.
2026-01-12 18:44:46 +01:00
CanbiZ
7f6ebeb119 Update build.func 2026-01-12 18:41:19 +01:00
community-scripts-pr-app[bot]
eb30288b1c Update CHANGELOG.md (#10750)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 17:13:42 +00:00
community-scripts-pr-app[bot]
5320b7dbad Update CHANGELOG.md (#10749)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 17:13:20 +00:00
CanbiZ (MickLesk)
27b55a5de4 Apache Guacamole: add schema upgrades and extension updates to Guacamole script (#10746) 2026-01-12 18:13:17 +01:00
CanbiZ (MickLesk)
ff76d83fa7 feat(storage): Add unified storage validation & fix GB/MB display (#10745) 2026-01-12 18:12:55 +01:00
community-scripts-pr-app[bot]
d0e22f73c6 Update CHANGELOG.md (#10748)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 17:12:01 +00:00
CanbiZ (MickLesk)
25594c30aa Apache Tomcat: update support and refactor install script (#10739) 2026-01-12 18:11:42 +01:00
CanbiZ (MickLesk)
c8f6786783 core: remove dupliocated pve_version in advanced installs (#10743) 2026-01-12 18:11:25 +01:00
CanbiZ (MickLesk)
a2a98cf26d remove locals 2026-01-12 18:02:41 +01:00
community-scripts-pr-app[bot]
a7a3514f92 Update CHANGELOG.md (#10744)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 15:50:57 +00:00
CanbiZ (MickLesk)
7e464cfdb0 refactor: Harmonize scripts and fix Booklore environment variables (#10742)
- apache-tomcat: Migrate to setup_java from tools.func
- apache-tomcat: Add update script with version detection from RELEASE-NOTES
- booklore: Fix environment variables (APP_PATH_CONFIG, APP_BOOKDROP_FOLDER)
- booklore: Remove unused variables (BOOKLORE_BOOKS_PATH, BOOKLORE_PORT)
- booklore: Refactor to use setup_mariadb_db and get_latest_github_release
- booklore: Add migration for old env vars in update script
- booklore: Add Node.js setup in update (was missing)
- booklore: Remove default nginx site to prevent conflicts
- jellystat: Replace custom get_ip() with import_local_ip
- jellystat: Remove unnecessary mkdir and simplify cd command
- jellystat: Use version variables for Node.js and PostgreSQL

Fixes #7499 (Booklore bookdrop issue)
2026-01-12 16:50:30 +01:00
community-scripts-pr-app[bot]
a1b381e920 Update .app files (#10735)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-01-12 14:21:54 +01:00
community-scripts-pr-app[bot]
9fca42fdea Update CHANGELOG.md (#10734)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:10:10 +00:00
CanbiZ (MickLesk)
57c87169a9 Apache Guacamole: Function Bump + update_script (#10728) 2026-01-12 14:09:46 +01:00
community-scripts-pr-app[bot]
0ec96f8287 Update CHANGELOG.md (#10733)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:05:27 +00:00
community-scripts-pr-app[bot]
c68f465fd1 Update date in json (#10732)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:05:24 +00:00
community-scripts-pr-app[bot]
235ed4f2ef Update CHANGELOG.md (#10731)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:05:17 +00:00
push-app-to-main[bot]
bf829988cc Jellystat (#10628)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
2026-01-12 14:05:03 +01:00
community-scripts-pr-app[bot]
176b41a576 Update CHANGELOG.md (#10730)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:04:52 +00:00
CanbiZ (MickLesk)
1ccf90cb27 core: validate container ID before pct create to prevent failures (#10729)
* feat: validate container ID before pct create to prevent failures

Add validation to ensure container IDs are not already in use before attempting to create containers. This prevents pct create failures when an ID is already assigned to a VM/LXC or used in LVM volumes.

Changes:
- Add validate_container_id() and get_valid_container_id() functions to build.func
- Validate ID in base_settings() for default installation method
- Validate ID in advanced_settings() dialog with user prompt for next available ID
- Add validation to turnkey.sh with interactive dialog
- Add validation to all-templates.sh with automatic ID correction

Checks performed:
- Container config file existence (/etc/pve/lxc/*.conf)
- VM config file existence (/etc/pve/qemu-server/*.conf)
- LVM logical volume usage

Fixes issue where container creation would fail if the suggested/chosen ID was already in use.

* feat: validate container ID before pct create to prevent failures

Add validation to ensure container IDs are not already in use before attempting to create containers. This prevents pct create failures when an ID is already assigned to a VM/LXC or used in LVM volumes.

Changes:
- Add validate_container_id() and get_valid_container_id() functions to build.func
- Validate ID in base_settings() for default installation method
- Validate ID in advanced_settings() dialog with user prompt for next available ID
- Add validation to turnkey.sh with interactive dialog
- Add validation to all-templates.sh with automatic ID correction

Checks performed:
- Container config file existence (/etc/pve/lxc/*.conf)
- VM config file existence (/etc/pve/qemu-server/*.conf)
- LVM logical volume usage

Fixes issue where container creation would fail if the suggested/chosen ID was already in use.

* Update turnkey.sh

* Update build.func
2026-01-12 14:04:28 +01:00
community-scripts-pr-app[bot]
97c6c4558a Update .app files (#10727)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:26:18 +01:00
community-scripts-pr-app[bot]
cabf3a877e Update CHANGELOG.md (#10726)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 12:23:14 +00:00
community-scripts-pr-app[bot]
96bdd76beb Update CHANGELOG.md (#10725)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 12:22:57 +00:00
CanbiZ (MickLesk)
7234ecc406 Apache CouchDB: bump to debian 13 and add update support (#10721)
* Apache CouchDB: bump to debian 13 and add update support

Added update functionality to apache-couchdb.sh and marked CouchDB as updateable in the JSON metadata. Updated default OS version to 13 and improved credential file handling. Refactored the install script to use a helper for repository setup and standardized credential output.

* fix naming
2026-01-12 13:22:50 +01:00
community-scripts-pr-app[bot]
f0a291542d Update CHANGELOG.md (#10724)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 12:22:36 +00:00
CanbiZ (MickLesk)
18e1149cad Apache Cassandra: bump to debian 13 and add update support (#10720)
* Apache Cassandra: bump to debian 13 and add update support

Bump default Cassandra version from 12 to 13 in scripts and metadata. Refactor install script to use helper functions for Java and repository setup. Implement update functionality in the control script and mark Cassandra as updateable in the JSON metadata.

* Add success message for Cassandra update

Add success message after updating Apache Cassandra.
2026-01-12 13:22:34 +01:00
CanbiZ (MickLesk)
6d05319eb3 Bump Argus to Debian 13 (#10718) 2026-01-12 13:22:15 +01:00
community-scripts-pr-app[bot]
7fe3a47d24 Update CHANGELOG.md (#10723)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 12:22:07 +00:00
CanbiZ (MickLesk)
fac82643a8 Cockpit: Downgrade to Debian 12 Bookworm (45Drives Issue) (#10717)
* Change default var_version from 13 to 12

* Update OS version from 13 to 12 in cockpit.json
2026-01-12 13:22:01 +01:00
CanbiZ (MickLesk)
e33d4d76fe Refactor Docker/Dockge & Bump to Debian 13 (#10719)
* Refactor Docker/Dockge & Bump to Debian 13

* Add base system update to Dockge update script

The update_script function now updates and upgrades the base system before updating Dockge. This ensures the system is up to date prior to pulling new Docker images.

* some fixes

* Apply suggestion from @tremor021

* Apply suggestion from @tremor021

---------

Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-01-12 13:21:39 +01:00
community-scripts-pr-app[bot]
d505f3df08 Update versions.json (#10722)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 13:06:22 +01:00
community-scripts-pr-app[bot]
fe471daff9 Update CHANGELOG.md (#10715)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 07:48:57 +00:00
CanbiZ (MickLesk)
76e7755956 Enforce non-interactive apt mode in DB setup scripts (#10714) 2026-01-12 08:48:36 +01:00
community-scripts-pr-app[bot]
166350d2ba Update CHANGELOG.md (#10713)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 00:16:31 +00:00
community-scripts-pr-app[bot]
75d1f6bfe4 Update versions.json (#10712)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-12 01:16:10 +01:00
community-scripts-pr-app[bot]
b8d67c08ad Update CHANGELOG.md (#10710)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 21:42:39 +00:00
Copilot
1c1a3abefc Fix Invoice Ninja Error 500 by restoring file ownership after artisan commands (#10709)
* Initial plan

* Fix Invoice Ninja Error 500 by ensuring proper file ownership after artisan commands

Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>
2026-01-11 22:42:19 +01:00
community-scripts-pr-app[bot]
5289dd256f Update CHANGELOG.md (#10707)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 17:07:12 +00:00
community-scripts-pr-app[bot]
674ed2c73f Update CHANGELOG.md (#10706)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 17:07:00 +00:00
Slaviša Arežina
e18a34ce63 Refactor: Infisical (#10693)
* Refactor

* Update

* Fix
2026-01-11 18:06:48 +01:00
community-scripts-pr-app[bot]
0090cb8b4b Update CHANGELOG.md (#10705)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 17:06:38 +00:00
Slaviša Arežina
b2602b83a0 Refactor (#10697) 2026-01-11 18:06:18 +01:00
community-scripts-pr-app[bot]
750b0a042e Update CHANGELOG.md (#10703)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 13:14:43 +00:00
Slaviša Arežina
932079a9f6 Refactor: Homer (#10698)
* Refactor

* Update
2026-01-11 14:14:19 +01:00
community-scripts-pr-app[bot]
d43899d5ad Update versions.json (#10702)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 13:05:58 +01:00
community-scripts-pr-app[bot]
b86a89e0fa Update CHANGELOG.md (#10696)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 00:17:34 +00:00
community-scripts-pr-app[bot]
bf9ceb9ce1 Update versions.json (#10695)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 01:17:06 +01:00
community-scripts-pr-app[bot]
328d2c2de1 Update CHANGELOG.md (#10692)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-10 16:26:06 +00:00
FutureCow
047dfb9c93 [Endurain] Increase default RAM from 2048 to 4096 (#10690)
* Increase default RAM from 2048 to 4096

For the new v0.16.5 2048 is not enough to build the app.

* Increase RAM allocation from 2048 to 4096
2026-01-10 17:25:46 +01:00
community-scripts-pr-app[bot]
d7fa87f349 Update versions.json (#10688)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-10 13:06:43 +01:00
community-scripts-pr-app[bot]
93827141fc Update CHANGELOG.md (#10686)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-10 10:42:11 +00:00
CanbiZ (MickLesk)
3e0d0f34cc fix(hwaccel): make beignet-opencl-icd optional for legacy Intel GPUs (#10677)
- Check if beignet-opencl-icd package is available before installation
- Package was removed in Debian 12+ and Ubuntu 22.04+
- VA-API hardware acceleration still works without OpenCL
- Prevents installation failure on systems with Intel HD 2000-5999 GPUs
2026-01-10 11:41:44 +01:00
community-scripts-pr-app[bot]
0a790bf544 Update CHANGELOG.md (#10679)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-10 00:15:38 +00:00
community-scripts-pr-app[bot]
570563539e Update versions.json (#10678)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-10 01:15:15 +01:00
community-scripts-pr-app[bot]
b5ad996bb2 Update CHANGELOG.md (#10675)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 20:20:13 +00:00
Tobias
d047d1aeb7 fix: setup_mariadb hangs on (#10672)
* fix: setup_mariadb hangs on

* readd: docs
2026-01-09 21:19:47 +01:00
community-scripts-pr-app[bot]
c3b5dc7c6f Update CHANGELOG.md (#10674)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 19:32:01 +00:00
Slaviša Arežina
2c1472bb58 Fixes (#10671) 2026-01-09 20:31:30 +01:00
community-scripts-pr-app[bot]
5b5bc11f1e Update CHANGELOG.md (#10666)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 14:19:28 +00:00
Slaviša Arežina
02bbfa5851 Fix (#10664) 2026-01-09 15:19:05 +01:00
community-scripts-pr-app[bot]
896e0c0257 Update versions.json (#10661)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 13:06:04 +01:00
community-scripts-pr-app[bot]
9cf17ef7df Update CHANGELOG.md (#10660)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 08:07:34 +00:00
Seth Gregory
f6f0a5553b Remove '--cpu' option from ExecStart command (#10659)
By default, the ExecStart in the system service includes the --cpu flag which forces ComfyUI to run entirely on CPU even if a GPU is present.  This commit removes that flag.
2026-01-09 09:07:11 +01:00
community-scripts-pr-app[bot]
580e86114a Update CHANGELOG.md (#10658)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 00:15:31 +00:00
community-scripts-pr-app[bot]
e9bfc49049 Update versions.json (#10657)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-09 01:15:04 +01:00
community-scripts-pr-app[bot]
4c8394d456 Update CHANGELOG.md (#10655)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 19:21:40 +00:00
chinedu40
87ba164188 Fix line continuation for vlc-bin installation (#10654) 2026-01-08 20:21:16 +01:00
community-scripts-pr-app[bot]
d427e9d313 Update CHANGELOG.md (#10653)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 14:29:15 +00:00
CanbiZ (MickLesk)
f474ea3d4a outline: use corepack yarn module (#10652)
Removed explicit installation of yarn via NODE_MODULE and switched to enabling corepack for Yarn management. Updated yarn install commands to use --immutable instead of --frozen-lockfile for improved reliability.
2026-01-08 15:28:52 +01:00
community-scripts-pr-app[bot]
77f69321f8 Update CHANGELOG.md (#10651)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 14:11:24 +00:00
CanbiZ (MickLesk)
1681033e39 Remove unnecessary quotes from variable expansions in VM scripts (#10649) 2026-01-08 15:10:57 +01:00
community-scripts-pr-app[bot]
741560b457 Update CHANGELOG.md (#10650)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 14:09:07 +00:00
Slaviša Arežina
422a01b0a5 Fix (#10634) 2026-01-08 15:08:34 +01:00
community-scripts-pr-app[bot]
2de935c549 Update .app files (#10647)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-01-08 15:06:59 +01:00
community-scripts-pr-app[bot]
c6176b1706 Update CHANGELOG.md (#10648)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 13:58:39 +00:00
community-scripts-pr-app[bot]
098dcdb2dc Update CHANGELOG.md (#10646)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 13:58:23 +00:00
community-scripts-pr-app[bot]
5ecfc2f666 Update date in json (#10645)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-01-08 13:58:15 +00:00
push-app-to-main[bot]
cddae63c63 GWN-Manager (#10642)
* Add gwn-manager (ct)

* Update gwn-manager.sh

* Update gwn-manager-install.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-01-08 14:57:56 +01:00
community-scripts-pr-app[bot]
64db3d3621 Update CHANGELOG.md (#10644)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 13:01:14 +00:00
Slaviša Arežina
468b5fbc38 deCONZ: Bump to Trixie base (#10643)
* Bump to Trixie

* Update

* Update
2026-01-08 14:00:48 +01:00
community-scripts-pr-app[bot]
8d973aa20e Update versions.json (#10641)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 13:07:03 +01:00
community-scripts-pr-app[bot]
74e4373e0f Update CHANGELOG.md (#10638)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-08 06:22:54 +00:00
Slaviša Arežina
1530256970 Update environment variables in tianji-install.sh (#10633) 2026-01-08 07:22:27 +01:00
75 changed files with 2107 additions and 978 deletions

View File

@@ -10,8 +10,116 @@
> [!CAUTION]
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
## 2026-01-13
## 2026-01-12
### 🆕 New Scripts
- Jellystat ([#10628](https://github.com/community-scripts/ProxmoxVE/pull/10628))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- InfluxSB: fix If / fi [@chrnie](https://github.com/chrnie) ([#10753](https://github.com/community-scripts/ProxmoxVE/pull/10753))
- Cockpit: Downgrade to Debian 12 Bookworm (45Drives Issue) [@MickLesk](https://github.com/MickLesk) ([#10717](https://github.com/community-scripts/ProxmoxVE/pull/10717))
- #### ✨ New Features
- InfluxDB: add setup for influxdb v3 [@victorlap](https://github.com/victorlap) ([#10736](https://github.com/community-scripts/ProxmoxVE/pull/10736))
- Apache Guacamole: add schema upgrades and extension updates [@MickLesk](https://github.com/MickLesk) ([#10746](https://github.com/community-scripts/ProxmoxVE/pull/10746))
- Apache Tomcat: update support and refactor install script + debian 13 [@MickLesk](https://github.com/MickLesk) ([#10739](https://github.com/community-scripts/ProxmoxVE/pull/10739))
- Apache Guacamole: Function Bump + update_script [@MickLesk](https://github.com/MickLesk) ([#10728](https://github.com/community-scripts/ProxmoxVE/pull/10728))
- Apache CouchDB: bump to debian 13 and add update support [@MickLesk](https://github.com/MickLesk) ([#10721](https://github.com/community-scripts/ProxmoxVE/pull/10721))
- Apache Cassandra: bump to debian 13 and add update support [@MickLesk](https://github.com/MickLesk) ([#10720](https://github.com/community-scripts/ProxmoxVE/pull/10720))
- #### 🔧 Refactor
- Refactor: Booklore [@MickLesk](https://github.com/MickLesk) ([#10742](https://github.com/community-scripts/ProxmoxVE/pull/10742))
- Bump Argus to Debian 13 [@MickLesk](https://github.com/MickLesk) ([#10718](https://github.com/community-scripts/ProxmoxVE/pull/10718))
- Refactor Docker/Dockge & Bump to Debian 13 [@MickLesk](https://github.com/MickLesk) ([#10719](https://github.com/community-scripts/ProxmoxVE/pull/10719))
### 💾 Core
- #### 🐞 Bug Fixes
- core: remove duplicated pve_version in advanced installs [@MickLesk](https://github.com/MickLesk) ([#10743](https://github.com/community-scripts/ProxmoxVE/pull/10743))
- #### ✨ New Features
- core: add storage validation & fix GB/MB display [@MickLesk](https://github.com/MickLesk) ([#10745](https://github.com/community-scripts/ProxmoxVE/pull/10745))
- core: validate container ID before pct create to prevent failures [@MickLesk](https://github.com/MickLesk) ([#10729](https://github.com/community-scripts/ProxmoxVE/pull/10729))
- #### 🔧 Refactor
- Enforce non-interactive apt mode in DB setup scripts [@MickLesk](https://github.com/MickLesk) ([#10714](https://github.com/community-scripts/ProxmoxVE/pull/10714))
## 2026-01-11
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Fix Invoice Ninja Error 500 by restoring file ownership after artisan commands [@Copilot](https://github.com/Copilot) ([#10709](https://github.com/community-scripts/ProxmoxVE/pull/10709))
- #### 🔧 Refactor
- Refactor: Infisical [@tremor021](https://github.com/tremor021) ([#10693](https://github.com/community-scripts/ProxmoxVE/pull/10693))
- Refactor: HortusFox [@tremor021](https://github.com/tremor021) ([#10697](https://github.com/community-scripts/ProxmoxVE/pull/10697))
- Refactor: Homer [@tremor021](https://github.com/tremor021) ([#10698](https://github.com/community-scripts/ProxmoxVE/pull/10698))
## 2026-01-10
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- [Endurain] Increase default RAM from 2048 to 4096 [@FutureCow](https://github.com/FutureCow) ([#10690](https://github.com/community-scripts/ProxmoxVE/pull/10690))
### 💾 Core
- #### 🐞 Bug Fixes
- tools.func: hwaccel - make beignet-opencl-icd optional for legacy Intel GPUs [@MickLesk](https://github.com/MickLesk) ([#10677](https://github.com/community-scripts/ProxmoxVE/pull/10677))
## 2026-01-09
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Jenkins: Fix application repository setup [@tremor021](https://github.com/tremor021) ([#10671](https://github.com/community-scripts/ProxmoxVE/pull/10671))
- deCONZ: Fix sources check in update script [@tremor021](https://github.com/tremor021) ([#10664](https://github.com/community-scripts/ProxmoxVE/pull/10664))
- Remove '--cpu' option from ExecStart command [@sethgregory](https://github.com/sethgregory) ([#10659](https://github.com/community-scripts/ProxmoxVE/pull/10659))
### 💾 Core
- #### 💥 Breaking Changes
- fix: setup_mariadb hangs on [@CrazyWolf13](https://github.com/CrazyWolf13) ([#10672](https://github.com/community-scripts/ProxmoxVE/pull/10672))
## 2026-01-08
### 🆕 New Scripts
- GWN-Manager ([#10642](https://github.com/community-scripts/ProxmoxVE/pull/10642))
### 🚀 Updated Scripts
- Fix line continuation for vlc-bin installation [@chinedu40](https://github.com/chinedu40) ([#10654](https://github.com/community-scripts/ProxmoxVE/pull/10654))
- #### 🐞 Bug Fixes
- outline: use corepack yarn module [@MickLesk](https://github.com/MickLesk) ([#10652](https://github.com/community-scripts/ProxmoxVE/pull/10652))
- Remove unnecessary quotes from variable expansions in VM scripts [@MickLesk](https://github.com/MickLesk) ([#10649](https://github.com/community-scripts/ProxmoxVE/pull/10649))
- Monica: Fix database variable names [@tremor021](https://github.com/tremor021) ([#10634](https://github.com/community-scripts/ProxmoxVE/pull/10634))
- Tianji: Fix PostrgreSQL vars [@tremor021](https://github.com/tremor021) ([#10633](https://github.com/community-scripts/ProxmoxVE/pull/10633))
- #### 🔧 Refactor
- deCONZ: Bump to Trixie base [@tremor021](https://github.com/tremor021) ([#10643](https://github.com/community-scripts/ProxmoxVE/pull/10643))
## 2026-01-07
### 🚀 Updated Scripts

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -20,15 +20,19 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/cassandra.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/init.d/cassandra ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Apache Cassandra"
$STD apt update
$STD apt install -y --only-upgrade cassandra cassandra-tools
msg_ok "Updated Apache Cassandra"
msg_ok "Updated successfully!"
exit
}
start

View File

@@ -5,13 +5,13 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://couchdb.apache.org/
APP="Apache-CouchDB"
APP="Apache CouchDB"
var_tags="${var_tags:-database}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-10}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -20,15 +20,19 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/couchdb.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
header_info
check_container_storage
check_container_resources
if [[ ! -f /usr/lib/systemd/system/couchdb.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Apache CouchDB"
$STD apt-get update
$STD apt-get install -y --only-upgrade couchdb
msg_ok "Updated Apache CouchDB"
msg_ok "Updated successfully!"
exit
}
start

View File

@@ -27,8 +27,196 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
setup_mariadb
msg_error "Currently we don't provide an update function for this ${APP}."
# Fetch latest versions
LATEST_TOMCAT=$(curl -fsSL https://dlcdn.apache.org/tomcat/tomcat-9/ | grep -oP '(?<=href=")v[^"/]+(?=/")' | sed 's/^v//' | sort -V | tail -n1)
LATEST_SERVER=$(curl -fsSL https://api.github.com/repos/apache/guacamole-server/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
LATEST_CLIENT=$(curl -fsSL https://api.github.com/repos/apache/guacamole-client/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
LATEST_MYSQL_CONNECTOR=$(curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/maven-metadata.xml" | grep -oP '<latest>\K[^<]+')
# Read current versions from ~/.guacamole_*
CURRENT_TOMCAT=$(cat ~/.guacamole_tomcat 2>/dev/null || echo "unknown")
CURRENT_SERVER=$(cat ~/.guacamole_server 2>/dev/null || echo "unknown")
CURRENT_CLIENT=$(cat ~/.guacamole_client 2>/dev/null || echo "unknown")
CURRENT_MYSQL_CONNECTOR=$(cat ~/.guacamole_mysql_connector 2>/dev/null || echo "unknown")
UPDATE_NEEDED=false
[[ "$CURRENT_TOMCAT" != "$LATEST_TOMCAT" ]] && UPDATE_NEEDED=true
[[ "$CURRENT_SERVER" != "$LATEST_SERVER" ]] && UPDATE_NEEDED=true
[[ "$CURRENT_CLIENT" != "$LATEST_CLIENT" ]] && UPDATE_NEEDED=true
[[ "$CURRENT_MYSQL_CONNECTOR" != "$LATEST_MYSQL_CONNECTOR" ]] && UPDATE_NEEDED=true
if [[ "$UPDATE_NEEDED" == "false" ]]; then
msg_ok "All components are up to date"
exit
fi
JAVA_VERSION="11" setup_java
msg_info "Stopping Services"
systemctl stop guacd tomcat
msg_ok "Stopped Services"
# Update Tomcat
if [[ "$CURRENT_TOMCAT" != "$LATEST_TOMCAT" ]]; then
msg_info "Updating Tomcat (${CURRENT_TOMCAT}${LATEST_TOMCAT})"
cp -a /opt/apache-guacamole/tomcat9/conf /tmp/tomcat-conf-backup
curl -fsSL "https://dlcdn.apache.org/tomcat/tomcat-9/v${LATEST_TOMCAT}/bin/apache-tomcat-${LATEST_TOMCAT}.tar.gz" | tar -xz -C /opt/apache-guacamole/tomcat9 --strip-components=1 --exclude='conf/*'
cp -a /tmp/tomcat-conf-backup/* /opt/apache-guacamole/tomcat9/conf/
rm -rf /tmp/tomcat-conf-backup
chown -R tomcat: /opt/apache-guacamole/tomcat9
echo "${LATEST_TOMCAT}" >~/.guacamole_tomcat
msg_ok "Updated Tomcat"
else
msg_ok "Tomcat already up to date (${CURRENT_TOMCAT})"
fi
# Update Guacamole Server
if [[ "$CURRENT_SERVER" != "$LATEST_SERVER" ]]; then
msg_info "Updating Guacamole Server (${CURRENT_SERVER}${LATEST_SERVER})"
rm -rf /opt/apache-guacamole/server/*
curl -fsSL "https://api.github.com/repos/apache/guacamole-server/tarball/refs/tags/${LATEST_SERVER}" | tar -xz --strip-components=1 -C /opt/apache-guacamole/server
cd /opt/apache-guacamole/server
export CPPFLAGS="-Wno-error=deprecated-declarations"
$STD autoreconf -fi
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
$STD make
$STD make install
$STD ldconfig
echo "${LATEST_SERVER}" >~/.guacamole_server
msg_ok "Updated Guacamole Server"
# Auth JDBC follows server version
msg_info "Updating Guacamole Auth JDBC"
rm -f /etc/guacamole/extensions/guacamole-auth-jdbc-mysql-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-jdbc-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-jdbc.tar.gz"
$STD tar -xf /tmp/guacamole-auth-jdbc.tar.gz -C /tmp
mv /tmp/guacamole-auth-jdbc-"${LATEST_SERVER}"/mysql/guacamole-auth-jdbc-mysql-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
rm -rf /tmp/guacamole-auth-jdbc*
echo "${LATEST_SERVER}" >~/.guacamole_auth_jdbc
msg_ok "Updated Guacamole Auth JDBC"
else
msg_ok "Guacamole Server already up to date (${CURRENT_SERVER})"
fi
# Update Guacamole Client
if [[ "$CURRENT_CLIENT" != "$LATEST_CLIENT" ]]; then
msg_info "Updating Guacamole Client (${CURRENT_CLIENT}${LATEST_CLIENT})"
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_CLIENT}/binary/guacamole-${LATEST_CLIENT}.war" -o "/opt/apache-guacamole/tomcat9/webapps/guacamole.war"
echo "${LATEST_CLIENT}" >~/.guacamole_client
msg_ok "Updated Guacamole Client"
else
msg_ok "Guacamole Client already up to date (${CURRENT_CLIENT})"
fi
# Update MySQL Connector
if [[ "$CURRENT_MYSQL_CONNECTOR" != "$LATEST_MYSQL_CONNECTOR" ]]; then
msg_info "Updating MySQL Connector (${CURRENT_MYSQL_CONNECTOR}${LATEST_MYSQL_CONNECTOR})"
curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${LATEST_MYSQL_CONNECTOR}/mysql-connector-j-${LATEST_MYSQL_CONNECTOR}.jar" -o "/etc/guacamole/lib/mysql-connector-j.jar"
echo "${LATEST_MYSQL_CONNECTOR}" >~/.guacamole_mysql_connector
msg_ok "Updated MySQL Connector"
else
msg_ok "MySQL Connector already up to date (${CURRENT_MYSQL_CONNECTOR})"
fi
# Apply SQL Schema Upgrades (CRITICAL!)
if [[ "$CURRENT_SERVER" != "$LATEST_SERVER" ]]; then
msg_info "Applying MySQL Schema Upgrades"
cd /tmp/guacamole-auth-jdbc-"${LATEST_SERVER}"/mysql/schema/upgrade/
UPGRADE_FILES=($(ls -1 upgrade-pre-*.sql 2>/dev/null | sort -V))
if [[ ${#UPGRADE_FILES[@]} -gt 0 ]]; then
for SQL_FILE in "${UPGRADE_FILES[@]}"; do
FILE_VERSION=$(echo ${SQL_FILE} | grep -oP 'upgrade-pre-\K[0-9\.]+(?=\.)')
# Apply upgrade if file version is newer than current but older/equal to target
if [[ $(echo -e "${FILE_VERSION}\n${CURRENT_SERVER}" | sort -V | head -n1) == "${CURRENT_SERVER}" && "${FILE_VERSION}" != "${CURRENT_SERVER}" ]]; then
msg_info "Applying schema patch: ${SQL_FILE}"
mysql -u root guacamole_db <"${SQL_FILE}" 2>/dev/null
if [[ $? -eq 0 ]]; then
msg_ok "Applied ${SQL_FILE}"
else
msg_warn "Failed to apply ${SQL_FILE} (may already be applied)"
fi
fi
done
fi
msg_ok "MySQL Schema updated"
fi
# Check and upgrade optional extensions
# TOTP Extension
if [[ -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar ]]; then
msg_info "Updating TOTP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-totp-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-totp-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-totp.tar.gz"
$STD tar -xf /tmp/guacamole-auth-totp.tar.gz -C /tmp
mv /tmp/guacamole-auth-totp-"${LATEST_SERVER}"/guacamole-auth-totp-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-totp-"${LATEST_SERVER}".jar
rm -rf /tmp/guacamole-auth-totp*
msg_ok "Updated TOTP Extension"
fi
# DUO Extension
if [[ -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar ]]; then
msg_info "Updating DUO Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-duo-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-duo-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-duo.tar.gz"
$STD tar -xf /tmp/guacamole-auth-duo.tar.gz -C /tmp
mv /tmp/guacamole-auth-duo-"${LATEST_SERVER}"/guacamole-auth-duo-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-duo-"${LATEST_SERVER}".jar
rm -rf /tmp/guacamole-auth-duo*
msg_ok "Updated DUO Extension"
fi
# LDAP Extension
if [[ -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar ]]; then
msg_info "Updating LDAP Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-ldap-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-ldap-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-ldap.tar.gz"
$STD tar -xf /tmp/guacamole-auth-ldap.tar.gz -C /tmp
mv /tmp/guacamole-auth-ldap-"${LATEST_SERVER}"/guacamole-auth-ldap-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-ldap-"${LATEST_SERVER}".jar
rm -rf /tmp/guacamole-auth-ldap*
msg_ok "Updated LDAP Extension"
fi
# Quick Connect Extension
if [[ -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar ]]; then
msg_info "Updating Quick Connect Extension"
rm -f /etc/guacamole/extensions/guacamole-auth-quickconnect-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-auth-quickconnect-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-auth-quickconnect.tar.gz"
$STD tar -xf /tmp/guacamole-auth-quickconnect.tar.gz -C /tmp
mv /tmp/guacamole-auth-quickconnect-"${LATEST_SERVER}"/guacamole-auth-quickconnect-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-auth-quickconnect-"${LATEST_SERVER}".jar
rm -rf /tmp/guacamole-auth-quickconnect*
msg_ok "Updated Quick Connect Extension"
fi
# History Recording Storage Extension
if [[ -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar ]]; then
msg_info "Updating History Recording Storage Extension"
rm -f /etc/guacamole/extensions/guacamole-history-recording-storage-*.jar
curl -fsSL "https://downloads.apache.org/guacamole/${LATEST_SERVER}/binary/guacamole-history-recording-storage-${LATEST_SERVER}.tar.gz" -o "/tmp/guacamole-history-recording-storage.tar.gz"
$STD tar -xf /tmp/guacamole-history-recording-storage.tar.gz -C /tmp
mv /tmp/guacamole-history-recording-storage-"${LATEST_SERVER}"/guacamole-history-recording-storage-"${LATEST_SERVER}".jar /etc/guacamole/extensions/
chmod 664 /etc/guacamole/extensions/guacamole-history-recording-storage-"${LATEST_SERVER}".jar
rm -rf /tmp/guacamole-history-recording-storage*
msg_ok "Updated History Recording Storage Extension"
fi
# Reset permissions and prepare for service start
msg_info "Resetting permissions"
mkdir -p /var/guacamole
chown daemon:daemon /var/guacamole
mkdir -p /home/daemon/.config/freerdp
chown daemon:daemon /home/daemon/.config/freerdp
msg_ok "Permissions reset"
msg_info "Starting Services"
systemctl daemon-reload
systemctl start tomcat guacd
msg_ok "Started Services"
msg_ok "Updated successfully!"
exit
}

View File

@@ -11,7 +11,7 @@ var_disk="${var_disk:-5}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -20,15 +20,79 @@ color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if ! ls -d /opt/tomcat-* >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_error "Currently we don't provide an update function for this ${APP}."
header_info
check_container_storage
check_container_resources
TOMCAT_DIR=$(ls -d /opt/tomcat-* 2>/dev/null | head -n1)
if [[ -z "$TOMCAT_DIR" || ! -d "$TOMCAT_DIR" ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
# Detect major version and current version from install path (e.g., /opt/tomcat-11 -> 11)
TOMCAT_MAJOR=$(basename "$TOMCAT_DIR" | grep -oP 'tomcat-\K[0-9]+')
if [[ -z "$TOMCAT_MAJOR" ]]; then
msg_error "Cannot determine Tomcat major version from path: $TOMCAT_DIR"
exit
fi
CURRENT_VERSION=$(grep -oP 'Apache Tomcat Version \K[0-9.]+' "$TOMCAT_DIR/RELEASE-NOTES" 2>/dev/null || echo "unknown")
LATEST_VERSION=$(curl -fsSL "https://dlcdn.apache.org/tomcat/tomcat-${TOMCAT_MAJOR}/" | grep -oP 'v[0-9]+\.[0-9]+\.[0-9]+(-M[0-9]+)?/' | sort -V | tail -n1 | sed 's/\/$//; s/v//')
if [[ -z "$LATEST_VERSION" ]]; then
msg_error "Failed to fetch latest version for Tomcat ${TOMCAT_MAJOR}"
exit
fi
if [[ "$CURRENT_VERSION" == "$LATEST_VERSION" ]]; then
msg_ok "${APP} ${CURRENT_VERSION} is already up to date"
exit
fi
msg_info "Stopping Tomcat service"
systemctl stop tomcat
msg_ok "Stopped Tomcat service"
msg_info "Backing up configuration and applications"
BACKUP_DIR="/tmp/tomcat-backup-$$"
mkdir -p "$BACKUP_DIR"
cp -a "$TOMCAT_DIR/conf" "$BACKUP_DIR/conf"
cp -a "$TOMCAT_DIR/webapps" "$BACKUP_DIR/webapps"
[[ -d "$TOMCAT_DIR/lib" ]] && cp -a "$TOMCAT_DIR/lib" "$BACKUP_DIR/lib"
msg_ok "Backed up configuration and applications"
msg_info "Downloading Tomcat ${LATEST_VERSION}"
TOMCAT_URL="https://dlcdn.apache.org/tomcat/tomcat-${TOMCAT_MAJOR}/v${LATEST_VERSION}/bin/apache-tomcat-${LATEST_VERSION}.tar.gz"
curl -fsSL "$TOMCAT_URL" -o /tmp/tomcat-update.tar.gz
msg_ok "Downloaded Tomcat ${LATEST_VERSION}"
msg_info "Installing update"
rm -rf "${TOMCAT_DIR:?}"/*
tar --strip-components=1 -xzf /tmp/tomcat-update.tar.gz -C "$TOMCAT_DIR"
rm -f /tmp/tomcat-update.tar.gz
msg_ok "Installed update"
msg_info "Restoring configuration and applications"
cp -a "$BACKUP_DIR/conf"/* "$TOMCAT_DIR/conf/"
cp -a "$BACKUP_DIR/webapps"/* "$TOMCAT_DIR/webapps/" 2>/dev/null || true
if [[ -d "$BACKUP_DIR/lib" ]]; then
for jar in "$BACKUP_DIR/lib"/*.jar; do
[[ -f "$jar" ]] || continue
jar_name=$(basename "$jar")
if [[ ! -f "$TOMCAT_DIR/lib/$jar_name" ]]; then
cp "$jar" "$TOMCAT_DIR/lib/"
fi
done
fi
rm -rf "$BACKUP_DIR"
chown -R root:root "$TOMCAT_DIR"
msg_ok "Restored configuration and applications"
msg_info "Starting Tomcat service"
systemctl start tomcat
msg_ok "Started Tomcat service"
msg_ok "Updated successfully!"
exit
}
start

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-3}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-3}"
var_ram="${var_ram:-3072}"
var_disk="${var_disk:-7}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -28,15 +28,29 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
setup_mariadb
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
JAVA_VERSION="21" setup_java
NODE_VERSION="22" setup_nodejs
setup_mariadb
setup_yq
msg_info "Stopping Service"
systemctl stop booklore
msg_info "Stopped Service"
msg_ok "Stopped Service"
msg_info "backup old install"
if grep -qE "^BOOKLORE_(DATA_PATH|BOOKDROP_PATH|BOOKS_PATH|PORT)=" /opt/booklore_storage/.env 2>/dev/null; then
msg_info "Migrating old environment variables"
sed -i 's/^BOOKLORE_DATA_PATH=/APP_PATH_CONFIG=/g' /opt/booklore_storage/.env
sed -i 's/^BOOKLORE_BOOKDROP_PATH=/APP_BOOKDROP_FOLDER=/g' /opt/booklore_storage/.env
sed -i '/^BOOKLORE_BOOKS_PATH=/d' /opt/booklore_storage/.env
sed -i '/^BOOKLORE_PORT=/d' /opt/booklore_storage/.env
msg_ok "Migrated old environment variables"
fi
msg_info "Backing up old installation"
mv /opt/booklore /opt/booklore_bak
msg_ok "backup done"
msg_ok "Backed up old installation"
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore" "tarball"
@@ -46,12 +60,9 @@ function update_script() {
$STD npm run build --configuration=production
msg_ok "Built Frontend"
JAVA_VERSION="21" setup_java
setup_yq
msg_info "Building Backend"
cd /opt/booklore/booklore-api
APP_VERSION=$(curl -fsSL https://api.github.com/repos/booklore-app/BookLore/releases/latest | yq '.tag_name' | sed 's/^v//')
APP_VERSION=$(get_latest_github_release "booklore-app/BookLore")
yq eval ".app.version = \"${APP_VERSION}\"" -i src/main/resources/application.yaml
$STD ./gradlew clean build --no-daemon
mkdir -p /opt/booklore/dist

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-0}"
header_info "$APP"
@@ -23,14 +23,14 @@ function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/apt/sources.list.d/deconz.list ]]; then
if [[ ! -f /etc/apt/sources.list.d/deconz.list && ! -f /etc/apt/sources.list.d/deconz.sources ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating $APP LXC"
$STD apt-get update
$STD apt-get -y upgrade
msg_ok "Updated $APP LXC"
msg_info "Updating deCONZ"
$STD apt update
$STD apt upgrade -y
msg_ok "Updated deCONZ"
msg_ok "Updated successfully!"
exit
}

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-4}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -24,33 +24,20 @@ function update_script() {
check_container_storage
check_container_resources
get_latest_release() {
curl -fsSL https://api.github.com/repos/"$1"/releases/latest | grep '"tag_name":' | cut -d'"' -f4
}
msg_info "Updating base system"
$STD apt-get update
$STD apt-get -y upgrade
$STD apt update
$STD apt upgrade -y
msg_ok "Base system updated"
msg_info "Updating Docker Engine"
$STD apt-get install --only-upgrade -y docker-ce docker-ce-cli containerd.io
$STD apt install --only-upgrade -y docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-buildx-plugin
msg_ok "Docker Engine updated"
if [[ -f /usr/local/lib/docker/cli-plugins/docker-compose ]]; then
COMPOSE_BIN="/usr/local/lib/docker/cli-plugins/docker-compose"
COMPOSE_NEW_VERSION=$(get_latest_release "docker/compose")
msg_info "Updating Docker Compose to $COMPOSE_NEW_VERSION"
curl -fsSL "https://github.com/docker/compose/releases/download/${COMPOSE_NEW_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \
-o "$COMPOSE_BIN"
chmod +x "$COMPOSE_BIN"
msg_ok "Docker Compose updated"
fi
if docker ps -a --format '{{.Image}}' | grep -q '^portainer/portainer-ce:latest$'; then
msg_info "Updating Portainer"
$STD docker pull portainer/portainer-ce:latest
$STD docker stop portainer && docker rm portainer
$STD docker stop portainer
$STD docker rm portainer
$STD docker volume create portainer_data >/dev/null 2>&1
$STD docker run -d \
-p 8000:8000 \
@@ -66,7 +53,8 @@ function update_script() {
if docker ps -a --format '{{.Names}}' | grep -q '^portainer_agent$'; then
msg_info "Updating Portainer Agent"
$STD docker pull portainer/agent:latest
$STD docker stop portainer_agent && docker rm portainer_agent
$STD docker stop portainer_agent
$STD docker rm portainer_agent
$STD docker run -d \
-p 9001:9001 \
--name=portainer_agent \

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-18}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -27,11 +27,17 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ${APP}"
msg_info "Updating base system"
$STD apt update
$STD apt upgrade -y
msg_ok "Base system updated"
msg_info "Updating Dockge"
cd /opt/dockge
$STD docker compose pull
$STD docker compose up -d
msg_ok "Updated ${APP}"
msg_ok "Updated Dockge"
msg_ok "Updated successfully!"
exit
}

View File

@@ -8,7 +8,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
APP="Endurain"
var_tags="${var_tags:-sport;social-media}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-5}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"

42
ct/gwn-manager.sh Normal file
View File

@@ -0,0 +1,42 @@
#!/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: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.grandstream.com/products/networking-solutions/wi-fi-management/product/gwn-manager
APP="GWN-Manager"
var_tags="${var_tags:-network;management}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-6144}"
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 /gwn ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_custom "🚀" "${GN}" "The app offers a built-in updater. Please use it."
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}https://${IP}:8443${CL}"

View File

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

6
ct/headers/gwn-manager Normal file
View File

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

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-2}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_version="${var_version:-13}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -27,36 +27,31 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Stopping Service"
systemctl stop homer
msg_ok "Stopped Service"
msg_info "Backing up assets directory"
cd ~
mkdir -p assets-backup
cp -R /opt/homer/assets/. assets-backup
msg_ok "Backed up assets directory"
if check_for_gh_release "homer" "bastienwirtz/homer"; then
msg_info "Stopping Service"
systemctl stop homer
msg_ok "Stopped Service"
msg_info "Updating ${APP}"
rm -rf /opt/homer/*
cd /opt/homer
curl -fsSL "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip" -o $(basename "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip")
$STD unzip homer.zip
msg_ok "Updated ${APP}"
msg_info "Backing up assets directory"
cd ~
mkdir -p assets-backup
cp -R /opt/homer/assets/. assets-backup
msg_ok "Backed up assets directory"
msg_info "Restoring assets directory"
cd ~
cp -Rf assets-backup/. /opt/homer/assets/
msg_ok "Restored assets directory"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "homer" "bastienwirtz/homer" "prebuild" "latest" "/opt/homer" "homer.zip"
msg_info "Cleaning"
rm -rf assets-backup /opt/homer/homer.zip
msg_ok "Cleaned"
msg_info "Starting Service"
systemctl start homer
msg_ok "Started Service"
msg_ok "Updated successfully!"
msg_info "Restoring assets directory"
cd ~
cp -Rf assets-backup/. /opt/homer/assets/
rm -rf assets-backup
msg_ok "Restored assets directory"
msg_info "Starting Service"
systemctl start homer
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}

View File

@@ -33,6 +33,7 @@ function update_script() {
msg_ok "Service stopped"
msg_info "Creating backup"
[[ -f /opt/infisical_backup.sql ]] && rm -f /opt/infisical_backup.sql
DB_PASS=$(grep -Po '(?<=^Database Password:\s).*' ~/infisical.creds | head -n1)
PGPASSWORD=$DB_PASS pg_dump -U infisical -h localhost -d infisical_db > /opt/infisical_backup.sql
msg_ok "Created backup"

View File

@@ -43,4 +43,4 @@ 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} and Port 8888 for v1 or Port 8086 (v2)${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP} and Port 8888 for v1, Port 8086 for v2 or Port 8181 for v3${CL}"

View File

@@ -32,7 +32,7 @@ function update_script() {
msg_info "Updating Jenkins"
$STD apt update
$STD apt -y upgrade
$STD apt upgrade -y
msg_ok "Updated Jenkins"
msg_ok "Updated successfully!"
exit

View File

@@ -28,7 +28,7 @@ function update_script() {
exit
fi
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
NODE_VERSION="22" setup_nodejs
if check_for_gh_release "outline" "outline/outline"; then
msg_info "Stopping Services"
@@ -46,7 +46,8 @@ function update_script() {
mv /opt/.env /opt/outline
export NODE_ENV=development
export NODE_OPTIONS="--max-old-space-size=3584"
$STD yarn install --frozen-lockfile
$STD corepack enable
$STD yarn install --immutable
export NODE_ENV=production
$STD yarn build
msg_ok "Updated ${APP}"

View File

@@ -6,7 +6,7 @@
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://cassandra.apache.org/doc/latest/",
@@ -23,7 +23,7 @@
"ram": 2048,
"hdd": 4,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -1,19 +1,19 @@
{
"name": "Apache-CouchDB",
"name": "Apache CouchDB",
"slug": "apache-couchdb",
"categories": [
8
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": 5984,
"documentation": "https://docs.couchdb.org/en/stable/",
"website": "https://couchdb.apache.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/couchdb.webp",
"config_path": "etc/default.ini",
"description": "Apache-CouchDB Seamless multi-master sync, that scales from Big Data to Mobile, with an Intuitive HTTP/JSON API and designed for Reliability.",
"description": "Apache CouchDB Seamless multi-master sync, that scales from Big Data to Mobile, with an Intuitive HTTP/JSON API and designed for Reliability.",
"install_methods": [
{
"type": "default",
@@ -23,7 +23,7 @@
"ram": 4096,
"hdd": 10,
"os": "debian",
"version": "12"
"version": "13"
}
}
],
@@ -33,7 +33,7 @@
},
"notes": [
{
"text": "Show Login Credentials: `cat CouchDB.creds`",
"text": "Login Credentials: `cat ~/couchdb.creds`",
"type": "info"
}
]

View File

@@ -6,7 +6,7 @@
],
"date_created": "2024-12-19",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://guacamole.apache.org/doc/gug/",

View File

@@ -6,7 +6,7 @@
],
"date_created": "2025-03-04",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://cwiki.apache.org/confluence/display/TOMCAT",
@@ -23,7 +23,7 @@
"ram": 1024,
"hdd": 5,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -20,10 +20,10 @@
"script": "ct/argus.sh",
"resources": {
"cpu": 1,
"ram": 256,
"ram": 512,
"hdd": 3,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -23,7 +23,7 @@
"ram": 3072,
"hdd": 7,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -23,7 +23,7 @@
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "13"
"version": "12"
}
}
],

View File

@@ -23,7 +23,7 @@
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -23,7 +23,7 @@
"ram": 2048,
"hdd": 4,
"os": "debian",
"version": "12"
"version": "13"
}
},
{

View File

@@ -23,7 +23,7 @@
"ram": 2048,
"hdd": 18,
"os": "debian",
"version": "12"
"version": "13"
}
}
],

View File

@@ -20,7 +20,7 @@
"script": "ct/endurain.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"ram": 4096,
"hdd": 5,
"os": "debian",
"version": "13"

View File

@@ -0,0 +1,40 @@
{
"name": "GWN Manager",
"slug": "gwn-manager",
"categories": [
9
],
"date_created": "2026-01-08",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8443,
"documentation": "https://documentation.grandstream.com/article-categories/gwn-mgmt/",
"website": "https://www.grandstream.com/products/networking-solutions/wi-fi-management/product/gwn-manager",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/gwn-manager.webp",
"config_path": "/gwn/conf/gwn.conf",
"description": "GWN Manager is a free on-premise enterprise-grade, management platform for Grandstream GWN series devices. Typically deployed on a customers private network, this flexible, scalable solution offers simplified configuration and management.",
"install_methods": [
{
"type": "default",
"script": "ct/gwn-manager.sh",
"resources": {
"cpu": 2,
"ram": 6144,
"hdd": 8,
"os": "debian",
"version": "13"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Installation package is pulled from GrandStream website. Installation may take a while.",
"type": "info"
}
]
}

View File

@@ -0,0 +1,48 @@
{
"name": "Jellystat",
"slug": "jellystat",
"categories": [
9
],
"date_created": "2026-01-12",
"type": "addon",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/CyferShepard/Jellystat",
"website": "https://github.com/CyferShepard/Jellystat",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/jellystat.webp",
"config_path": "/opt/jellystat/.env",
"description": "A free and open source statistics app for Jellyfin",
"install_methods": [
{
"type": "default",
"script": "tools/addon/jellystat.sh",
"resources": {
"cpu": null,
"ram": null,
"hdd": null,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Requires Node.js 20+ and PostgreSQL (auto-installed if missing)",
"type": "info"
},
{
"text": "Default PostgreSQL credentials: jellystat / jellystat",
"type": "info"
},
{
"text": "Update with: update_jellystat",
"type": "info"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,22 +13,16 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y apt-transport-https
msg_ok "Installed Dependencies"
msg_info "Installing Eclipse Temurin (Patience)"
curl -fsSL "https://packages.adoptium.net/artifactory/api/gpg/key/public" | gpg --dearmor >/etc/apt/trusted.gpg.d/adoptium.gpg
echo 'deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main' >/etc/apt/sources.list.d/adoptium.list
$STD apt-get update
$STD apt-get install -y temurin-11-jdk
msg_ok "Installed Eclipse Temurin"
JAVA_VERSION="11" setup_java
msg_info "Installing Apache Cassandra"
curl -fsSL "https://downloads.apache.org/cassandra/KEYS" | gpg --dearmor >/etc/apt/trusted.gpg.d/cassandra.gpg
echo "deb https://debian.cassandra.apache.org 41x main" >/etc/apt/sources.list.d/cassandra.sources.list
$STD apt-get update
$STD apt-get install -y cassandra cassandra-tools
setup_deb822_repo \
"cassandra" \
"https://downloads.apache.org/cassandra/KEYS" \
"https://debian.cassandra.apache.org" \
"41x" \
"main"
$STD apt install -y cassandra cassandra-tools
sed -i -e 's/^rpc_address: localhost/#rpc_address: localhost/g' -e 's/^# rpc_interface: eth1/rpc_interface: eth0/g' /etc/cassandra/cassandra.yaml
msg_ok "Installed Apache Cassandra"

View File

@@ -13,10 +13,6 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y apt-transport-https
msg_ok "Installed Dependencies"
msg_info "Installing Apache CouchDB"
ERLANG_COOKIE=$(openssl rand -base64 32)
ADMIN_PASS="$(openssl rand -base64 18 | cut -c1-13)"
@@ -25,14 +21,19 @@ debconf-set-selections <<<"couchdb couchdb/mode select standalone"
debconf-set-selections <<<"couchdb couchdb/bindaddress string 0.0.0.0"
debconf-set-selections <<<"couchdb couchdb/adminpass password $ADMIN_PASS"
debconf-set-selections <<<"couchdb couchdb/adminpass_again password $ADMIN_PASS"
curl -fsSL https://couchdb.apache.org/repo/keys.asc | gpg --dearmor -o /usr/share/keyrings/couchdb-archive-keyring.gpg
VERSION_CODENAME="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
echo "deb [signed-by=/usr/share/keyrings/couchdb-archive-keyring.gpg] https://apache.jfrog.io/artifactory/couchdb-deb/ ${VERSION_CODENAME} main" >/etc/apt/sources.list.d/couchdb.sources.list
$STD apt-get update
$STD apt-get install -y couchdb
echo -e "CouchDB Erlang Cookie: \e[32m$ERLANG_COOKIE\e[0m" >>~/CouchDB.creds
echo -e "CouchDB Admin Password: \e[32m$ADMIN_PASS\e[0m" >>~/CouchDB.creds
msg_ok "Installed Apache CouchDB."
setup_deb822_repo \
"couchdb" \
"https://couchdb.apache.org/repo/keys.asc" \
"https://apache.jfrog.io/artifactory/couchdb-deb" \
"$(get_os_info codename)" \
"main"
$STD apt install -y couchdb
{
echo "CouchDB Credentials"
echo "CouchDB Erlang Cookie: $ERLANG_COOKIE"
echo "CouchDB Admin Password: $ADMIN_PASS"
} >>~/couchdb.creds
msg_ok "Installed Apache CouchDB"
motd_ssh
customize

View File

@@ -15,12 +15,11 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
build-essential \
jq \
libcairo2-dev \
libturbojpeg0 \
libjpeg62-turbo-dev \
libpng-dev \
libtool-bin \
libossp-uuid-dev \
uuid-dev \
libvncserver-dev \
freerdp3-dev \
libssh2-1-dev \
@@ -34,71 +33,60 @@ $STD apt install -y \
libswscale-dev \
libavcodec-dev \
libavutil-dev \
libavformat-dev \
default-jdk
libavformat-dev
msg_ok "Installed Dependencies"
JAVA_VERSION="11" setup_java
setup_mariadb
MARIADB_DB_NAME="guacamole_db" MARIADB_DB_USER="guacamole_user" setup_mariadb_db
msg_info "Setup Apache Tomcat"
RELEASE=$(curl -fsSL https://dlcdn.apache.org/tomcat/tomcat-9/ | grep -oP '(?<=href=")v[^"/]+(?=/")' | sed 's/^v//' | sort -V | tail -n1)
mkdir -p /opt/apache-guacamole/tomcat9
mkdir -p /opt/apache-guacamole/server
curl -fsSL "https://dlcdn.apache.org/tomcat/tomcat-9/v${RELEASE}/bin/apache-tomcat-${RELEASE}.tar.gz" | tar -xz -C /opt/apache-guacamole/tomcat9 --strip-components=1
TOMCAT_VERSION=$(curl -fsSL https://dlcdn.apache.org/tomcat/tomcat-9/ | grep -oP '(?<=href=")v[^"/]+(?=/")' | sed 's/^v//' | sort -V | tail -n1)
mkdir -p /opt/apache-guacamole/{tomcat9,server}
curl -fsSL "https://dlcdn.apache.org/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz" | tar -xz -C /opt/apache-guacamole/tomcat9 --strip-components=1
useradd -r -d /opt/apache-guacamole/tomcat9 -s /bin/false tomcat
chown -R tomcat: /opt/apache-guacamole/tomcat9
chmod -R g+r /opt/apache-guacamole/tomcat9/conf
chmod g+x /opt/apache-guacamole/tomcat9/conf
msg_ok "Setup Apache Tomcat"
echo "${TOMCAT_VERSION}" >~/.guacamole_tomcat
msg_ok "Setup Apache Tomcat ${TOMCAT_VERSION}"
msg_info "Setup Apache Guacamole"
mkdir -p /etc/guacamole/{extensions,lib}
RELEASE_SERVER=$(curl -fsSL https://api.github.com/repos/apache/guacamole-server/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
curl -fsSL "https://api.github.com/repos/apache/guacamole-server/tarball/refs/tags/${RELEASE_SERVER}" | tar -xz --strip-components=1 -C /opt/apache-guacamole/server
GUAC_SERVER_VERSION=$(curl -fsSL https://api.github.com/repos/apache/guacamole-server/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
GUAC_CLIENT_VERSION=$(curl -fsSL https://api.github.com/repos/apache/guacamole-client/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
MYSQL_CONNECTOR_VERSION=$(curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/maven-metadata.xml" | grep -oP '<latest>\K[^<]+')
curl -fsSL "https://api.github.com/repos/apache/guacamole-server/tarball/refs/tags/${GUAC_SERVER_VERSION}" | tar -xz --strip-components=1 -C /opt/apache-guacamole/server
cd /opt/apache-guacamole/server
export CPPFLAGS="-Wno-error=deprecated-declarations"
$STD autoreconf -fi
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots --disable-guaclog
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
$STD make
$STD make install
$STD ldconfig
RELEASE_CLIENT=$(curl -fsSL https://api.github.com/repos/apache/guacamole-client/tags | jq -r '.[].name' | grep -v -- '-RC' | head -n 1)
curl -fsSL "https://downloads.apache.org/guacamole/${RELEASE_CLIENT}/binary/guacamole-${RELEASE_CLIENT}.war" -o "/opt/apache-guacamole/tomcat9/webapps/guacamole.war"
cd /root
curl -fsSL "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-9.3.0.tar.gz" -o "/root/mysql-connector-j-9.3.0.tar.gz"
$STD tar -xf ~/mysql-connector-j-9.3.0.tar.gz
mv ~/mysql-connector-j-9.3.0/mysql-connector-j-9.3.0.jar /etc/guacamole/lib/
curl -fsSL "https://downloads.apache.org/guacamole/${RELEASE_SERVER}/binary/guacamole-auth-jdbc-${RELEASE_SERVER}.tar.gz" -o "/root/guacamole-auth-jdbc-${RELEASE_SERVER}.tar.gz"
$STD tar -xf ~/guacamole-auth-jdbc-"$RELEASE_SERVER".tar.gz
mv ~/guacamole-auth-jdbc-"$RELEASE_SERVER"/mysql/guacamole-auth-jdbc-mysql-"$RELEASE_SERVER".jar /etc/guacamole/extensions/
rm -rf ~/mysql-connector-j-9.3.0{,.tar.gz}
echo "${GUAC_SERVER_VERSION}" >~/.guacamole_server
curl -fsSL "https://downloads.apache.org/guacamole/${GUAC_CLIENT_VERSION}/binary/guacamole-${GUAC_CLIENT_VERSION}.war" -o "/opt/apache-guacamole/tomcat9/webapps/guacamole.war"
echo "${GUAC_CLIENT_VERSION}" >~/.guacamole_client
curl -fsSL "https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/${MYSQL_CONNECTOR_VERSION}/mysql-connector-j-${MYSQL_CONNECTOR_VERSION}.jar" -o "/etc/guacamole/lib/mysql-connector-j.jar"
echo "${MYSQL_CONNECTOR_VERSION}" >~/.guacamole_mysql_connector
curl -fsSL "https://downloads.apache.org/guacamole/${GUAC_SERVER_VERSION}/binary/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz" -o "/root/guacamole-auth-jdbc-${GUAC_SERVER_VERSION}.tar.gz"
$STD tar -xf ~/guacamole-auth-jdbc-"$GUAC_SERVER_VERSION".tar.gz
mv ~/guacamole-auth-jdbc-"$GUAC_SERVER_VERSION"/mysql/guacamole-auth-jdbc-mysql-"$GUAC_SERVER_VERSION".jar /etc/guacamole/extensions/
echo "${GUAC_SERVER_VERSION}" >~/.guacamole_auth_jdbc
msg_ok "Setup Apache Guacamole"
msg_info "Setup Database"
DB_NAME=guacamole_db
DB_USER=guacamole_user
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
$STD mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
{
echo "Guacamole-Credentials"
echo "Database User: $DB_USER"
echo "Database Password: $DB_PASS"
echo "Database Name: $DB_NAME"
} >>~/guacamole.creds
cd guacamole-auth-jdbc-"${RELEASE_SERVER}"/mysql/schema
cat *.sql | mariadb -u root ${DB_NAME}
msg_info "Importing Database Schema"
cd ~/guacamole-auth-jdbc-"${GUAC_SERVER_VERSION}"/mysql/schema
cat *.sql | mariadb -u root ${MARIADB_DB_NAME}
{
echo "mysql-hostname: 127.0.0.1"
echo "mysql-port: 3306"
echo "mysql-database: $DB_NAME"
echo "mysql-username: $DB_USER"
echo "mysql-password: $DB_PASS"
echo "mysql-database: $MARIADB_DB_NAME"
echo "mysql-username: $MARIADB_DB_USER"
echo "mysql-password: $MARIADB_DB_PASS"
} >>/etc/guacamole/guacamole.properties
rm -rf ~/guacamole-auth-jdbc-"$RELEASE_SERVER"{,.tar.gz}
msg_ok "Setup Database"
rm -rf ~/guacamole-auth-jdbc-"$GUAC_SERVER_VERSION"{,.tar.gz}
msg_ok "Imported Database Schema"
msg_info "Setup Service"
cat <<EOF >/etc/guacamole/guacd.conf
@@ -143,7 +131,7 @@ PIDFile=/var/run/guacd.pid
[Install]
WantedBy=multi-user.target
EOF
systemctl -q enable --now mysql tomcat guacd
systemctl enable -q --now mysql tomcat guacd
msg_ok "Setup Service"
motd_ssh

View File

@@ -13,19 +13,6 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y \
lsb-release \
apt-transport-https
msg_ok "Installed Dependencies"
msg_info "Setting up Adoptium Repository"
mkdir -p /etc/apt/keyrings
curl -fsSL "https://packages.adoptium.net/artifactory/api/gpg/key/public" | gpg --dearmor >/etc/apt/trusted.gpg.d/adoptium.gpg
echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" >/etc/apt/sources.list.d/adoptium.list
$STD apt-get update
msg_ok "Set up Adoptium Repository"
read -r -p "${TAB3}Which Tomcat version would you like to install? (9, 10.1, 11): " version
case $version in
9)
@@ -33,25 +20,8 @@ case $version in
echo "Which LTS Java version would you like to use? (8, 11, 17, 21): "
read -r jdk_version
case $jdk_version in
8)
msg_info "Installing Temurin JDK 8 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-8-jdk
msg_ok "Setup Temurin JDK 8 (LTS)"
;;
11)
msg_info "Installing Temurin JDK 11 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-11-jdk
msg_ok "Setup Temurin JDK 11 (LTS)"
;;
17)
msg_info "Installing Temurin JDK 17 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -qqy temurin-17-jdk
msg_ok "Setup Temurin JDK 17 (LTS)"
;;
21)
msg_info "Installing Temurin JDK 21 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-21-jdk
msg_ok "Setup Temurin JDK 21 (LTS)"
8 | 11 | 17 | 21)
JAVA_VERSION="$jdk_version" setup_java
;;
*)
msg_error "Invalid JDK version selected. Please enter 8, 11, 17 or 21."
@@ -61,26 +31,14 @@ case $version in
;;
10 | 10.1)
TOMCAT_VERSION="10"
echo "Which LTS Java version would you like to use? (11, 17): "
echo "Which LTS Java version would you like to use? (11, 17, 21): "
read -r jdk_version
case $jdk_version in
11)
msg_info "Installing Temurin JDK 11 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-11-jdk
msg_ok "Setup Temurin JDK 11"
;;
17)
msg_info "Installing Temurin JDK 17 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-17-jdk
msg_ok "Setup Temurin JDK 17"
;;
21)
msg_info "Installing Temurin JDK 21 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-21-jdk
msg_ok "Setup Temurin JDK 21 (LTS)"
11 | 17 | 21)
JAVA_VERSION="$jdk_version" setup_java
;;
*)
msg_error "Invalid JDK version selected. Please enter 11 or 17."
msg_error "Invalid JDK version selected. Please enter 11, 17 or 21."
exit 1
;;
esac
@@ -90,15 +48,8 @@ case $version in
echo "Which LTS Java version would you like to use? (17, 21): "
read -r jdk_version
case $jdk_version in
17)
msg_info "Installing Temurin JDK 17 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -qqy temurin-17-jdk
msg_ok "Setup Temurin JDK 17"
;;
21)
msg_info "Installing Temurin JDK 21 (LTS) for Tomcat $TOMCAT_VERSION"
$STD apt-get install -y temurin-21-jdk
msg_ok "Setup Temurin JDK 21 (LTS)"
17 | 21)
JAVA_VERSION="$jdk_version" setup_java
;;
*)
msg_error "Invalid JDK version selected. Please enter 17 or 21."

View File

@@ -14,30 +14,15 @@ network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y nginx
$STD apt install -y nginx
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore" "tarball"
JAVA_VERSION="21" setup_java
NODE_VERSION="22" setup_nodejs
setup_mariadb
setup_yq
msg_info "Setting up database"
DB_NAME=booklore_db
DB_USER=booklore_user
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
$STD mariadb -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost';"
$STD mariadb -u root -e "GRANT SELECT ON \`mysql\`.\`time_zone_name\` TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
{
echo "BookLore Database Credentials"
echo "Database: $DB_NAME"
echo "Username: $DB_USER"
echo "Password: $DB_PASS"
} >>~/booklore.creds
msg_ok "Set up database"
MARIADB_DB_NAME="booklore_db" MARIADB_DB_USER="booklore_user" MARIADB_DB_EXTRA_GRANTS="GRANT SELECT ON \`mysql\`.\`time_zone_name\`" setup_mariadb_db
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore" "tarball"
msg_info "Building Frontend"
cd /opt/booklore/booklore-ui
@@ -46,22 +31,22 @@ $STD npm run build --configuration=production
msg_ok "Built Frontend"
msg_info "Creating Environment"
mkdir -p /opt/booklore_storage{/data,/books,/bookdrop}
mkdir -p /opt/booklore_storage/{data,books,bookdrop}
cat <<EOF >/opt/booklore_storage/.env
DATABASE_URL=jdbc:mariadb://localhost:3306/$DB_NAME
DATABASE_USERNAME=$DB_USER
DATABASE_PASSWORD=$DB_PASS
BOOKLORE_PORT=6060
# Database Configuration
DATABASE_URL=jdbc:mariadb://localhost:3306/${MARIADB_DB_NAME}
DATABASE_USERNAME=${MARIADB_DB_USER}
DATABASE_PASSWORD=${MARIADB_DB_PASS}
BOOKLORE_DATA_PATH=/opt/booklore_storage/data
BOOKLORE_BOOKS_PATH=/opt/booklore_storage/books
BOOKLORE_BOOKDROP_PATH=/opt/booklore_storage/bookdrop
# App Configuration (Spring Boot mapping from app.* properties)
APP_PATH_CONFIG=/opt/booklore_storage/data
APP_BOOKDROP_FOLDER=/opt/booklore_storage/bookdrop
EOF
msg_ok "Created Environment"
msg_info "Building Backend"
cd /opt/booklore/booklore-api
APP_VERSION=$(curl -fsSL https://api.github.com/repos/booklore-app/BookLore/releases/latest | yq '.tag_name' | sed 's/^v//')
APP_VERSION=$(get_latest_github_release "booklore-app/BookLore")
yq eval ".app.version = \"${APP_VERSION}\"" -i src/main/resources/application.yaml
$STD ./gradlew clean build --no-daemon
mkdir -p /opt/booklore/dist
@@ -73,22 +58,24 @@ fi
cp "$JAR_PATH" /opt/booklore/dist/app.jar
msg_ok "Built Backend"
msg_info "Configure Nginx"
msg_info "Configuring Nginx"
rm -rf /usr/share/nginx/html
ln -s /opt/booklore/booklore-ui/dist/booklore/browser /usr/share/nginx/html
rm -f /etc/nginx/sites-enabled/default
cp /opt/booklore/nginx.conf /etc/nginx/nginx.conf
sed -i 's/listen \${BOOKLORE_PORT};/listen 6060;/' /etc/nginx/nginx.conf
sed -i 's/listen \[::\]:${BOOKLORE_PORT};/listen [::]:6060;/' /etc/nginx/nginx.conf
systemctl restart nginx
msg_ok "Configured Nginx"
msg_info "Creating Systemd Service"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/booklore.service
[Unit]
Description=BookLore Java Service
After=network.target
After=network.target mariadb.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/booklore/dist
ExecStart=/usr/bin/java -jar /opt/booklore/dist/app.jar
@@ -102,7 +89,7 @@ RestartSec=5
WantedBy=multi-user.target
EOF
systemctl enable -q --now booklore
msg_ok "Created BookLore Service"
msg_ok "Created Service"
motd_ssh
customize

View File

@@ -72,7 +72,7 @@ After=network.target
Type=simple
User=root
WorkingDirectory=/opt/ComfyUI
ExecStart=/opt/ComfyUI/venv/bin/python /opt/ComfyUI/main.py --listen --port 8188 --cpu
ExecStart=/opt/ComfyUI/venv/bin/python /opt/ComfyUI/main.py --listen --port 8188
Restart=on-failure
[Install]

View File

@@ -14,17 +14,18 @@ network_check
update_os
msg_info "Setting Phoscon Repository"
VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
curl -fsSL "http://phoscon.de/apt/deconz.pub.key" >/etc/apt/trusted.gpg.d/deconz.pub.asc
echo "deb [arch=amd64] http://phoscon.de/apt/deconz $VERSION main" >/etc/apt/sources.list.d/deconz.list
setup_deb822_repo \
"deconz" \
"http://phoscon.de/apt/deconz.pub.key" \
"http://phoscon.de/apt/deconz" \
"generic"
msg_ok "Setup Phoscon Repository"
msg_info "Installing deConz"
libssl=$(curl -fsSL "http://security.ubuntu.com/ubuntu/pool/main/o/openssl/" | grep -o 'libssl1\.1_1\.1\.1f-1ubuntu2\.2[^"]*amd64\.deb' | head -n1)
curl -fsSL "http://security.ubuntu.com/ubuntu/pool/main/o/openssl/$libssl" -o "$libssl"
$STD dpkg -i "$libssl"
$STD apt-get update
$STD apt-get install -y deconz
$STD apt install -y deconz
rm -rf "$libssl"
msg_ok "Installed deConz"

View File

@@ -23,7 +23,7 @@ $STD apt install -y \
redis-server \
ffmpeg \
procps \
vlc-bin \
vlc-bin \
vlc-plugin-base \
streamlink
msg_ok "Installed Dependencies"

View File

@@ -13,32 +13,17 @@ setting_up_container
network_check
update_os
get_latest_release() {
curl -fsSL https://api.github.com/repos/"$1"/releases/latest | grep '"tag_name":' | cut -d'"' -f4
}
DOCKER_LATEST_VERSION=$(get_latest_github_release "moby/moby")
PORTAINER_LATEST_VERSION=$(get_latest_github_release "portainer/portainer")
PORTAINER_AGENT_LATEST_VERSION=$(get_latest_github_release "portainer/agent")
DOCKER_LATEST_VERSION=$(get_latest_release "moby/moby")
PORTAINER_LATEST_VERSION=$(get_latest_release "portainer/portainer")
PORTAINER_AGENT_LATEST_VERSION=$(get_latest_release "portainer/agent")
DOCKER_COMPOSE_LATEST_VERSION=$(get_latest_release "docker/compose")
msg_info "Installing Docker $DOCKER_LATEST_VERSION"
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"
read -r -p "${TAB3}Install Docker Compose v2 plugin? <y/N> " prompt_compose
if [[ ${prompt_compose,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
mkdir -p /usr/local/lib/docker/cli-plugins
curl -fsSL "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_LATEST_VERSION}/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/lib/docker/cli-plugins/docker-compose
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
msg_ok "Installed Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
fi
read -r -p "${TAB3}Would you like to add Portainer (UI)? <y/N> " prompt
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"

View File

@@ -13,27 +13,15 @@ setting_up_container
network_check
update_os
get_latest_release() {
curl -fsSL https://api.github.com/repos/$1/releases/latest | grep '"tag_name":' | cut -d'"' -f4
}
DOCKER_LATEST_VERSION=$(get_latest_github_release "moby/moby")
DOCKER_LATEST_VERSION=$(get_latest_release "moby/moby")
DOCKER_COMPOSE_LATEST_VERSION=$(get_latest_release "docker/compose")
msg_info "Installing Docker $DOCKER_LATEST_VERSION"
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 Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -fsSL https://github.com/docker/compose/releases/download/$DOCKER_COMPOSE_LATEST_VERSION/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
msg_ok "Installed Docker Compose $DOCKER_COMPOSE_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"

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Slaviša Arežina (tremor021)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.grandstream.com/products/networking-solutions/wi-fi-management/product/gwn-manager
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 \
xfonts-utils \
fontconfig
msg_ok "Installed Dependencies"
msg_info "Setting up GWN Manager (Patience)"
RELEASE=$(curl -fsSL https://www.grandstream.com/support/tools#gwntools \
| grep -oP 'https://firmware\.grandstream\.com/GWN_Manager-[^"]+-Ubuntu\.tar\.gz')
download_file "$RELEASE" "/tmp/gwnmanager.tar.gz"
cd /tmp
tar -xzf gwnmanager.tar.gz --strip-components=1
$STD ./install
msg_ok "Setup GWN Manager"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/gwnmanager.service
[Unit]
Description=GWN Manager
After=network.target
Requires=network.target
[Service]
Type=simple
WorkingDirectory=/gwn
ExecStart=/gwn/gwn start
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q gwnmanager
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -13,32 +13,25 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt-get install -y pip
msg_ok "Installed Dependencies"
msg_info "Installing Homer"
mkdir -p /opt/homer
cd /opt/homer
curl -fsSL "https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip" -o "homer.zip"
$STD unzip homer.zip
rm -rf homer.zip
cp assets/config.yml.dist assets/config.yml
msg_ok "Installed Homer"
fetch_and_deploy_gh_release "homer" "bastienwirtz/homer" "prebuild" "latest" "/opt/homer" "homer.zip"
cp /opt/homer/assets/config.yml.dist /opt/homer/assets/config.yml
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/homer.service
[Unit]
Description=Homer Dashboard
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/homer
ExecStart=python3 -m http.server 8010
[Install]
WantedBy=multi-user.target
EOF
$STD systemctl enable --now homer
systemctl enable -q --now homer
msg_ok "Created Service"
motd_ssh

View File

@@ -13,37 +13,18 @@ setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y apache2
msg_ok "Installed Dependencies"
setup_mariadb
MARIADB_DB_NAME="hortusfox" MARIADB_DB_USER="hortusfox" setup_mariadb_db
PHP_MODULE="exif,mysql" PHP_APACHE="YES" PHP_FPM="NO" PHP_VERSION="8.3" setup_php
setup_composer
msg_info "Setting up database"
DB_NAME=hortusfox
DB_USER=hortusfox
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
$STD mariadb -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
{
echo "HortusFox Database Credentials"
echo "Database: $DB_NAME"
echo "Username: $DB_USER"
echo "Password: $DB_PASS"
} >>~/hortusfox.creds
msg_ok "Set up database"
fetch_and_deploy_gh_release "hortusfox" "danielbrendel/hortusfox-web" "tarball"
msg_info "Configuring .env"
cp /opt/hortusfox/.env.example /opt/hortusfox/.env
sed -i "s|^DB_HOST=.*|DB_HOST=localhost|" /opt/hortusfox/.env
sed -i "s|^DB_USER=.*|DB_USER=$DB_USER|" /opt/hortusfox/.env
sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$DB_PASS|" /opt/hortusfox/.env
sed -i "s|^DB_DATABASE=.*|DB_DATABASE=$DB_NAME|" /opt/hortusfox/.env
sed -i "s|^DB_USER=.*|DB_USER=$MARIADB_DB_USER|" /opt/hortusfox/.env
sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD=$MARIADB_DB_PASS|" /opt/hortusfox/.env
sed -i "s|^DB_DATABASE=.*|DB_DATABASE=$MARIADB_DB_NAME|" /opt/hortusfox/.env
sed -i "s|^DB_ENABLE=.*|DB_ENABLE=true|" /opt/hortusfox/.env
sed -i "s|^APP_TIMEZONE=.*|APP_TIMEZONE=Europe/Berlin|" /opt/hortusfox/.env
msg_ok ".env configured"
@@ -58,20 +39,20 @@ $STD php asatru migrate:fresh
msg_ok "Migration finished"
msg_info "Setting up HortusFox"
$STD mariadb -u root -D $DB_NAME -e "INSERT IGNORE INTO AppModel (workspace, language, created_at) VALUES ('Default Workspace', 'en', NOW());"
$STD mariadb -u root -D $MARIADB_DB_NAME -e "INSERT IGNORE INTO AppModel (workspace, language, created_at) VALUES ('Default Workspace', 'en', NOW());"
$STD php asatru plants:attributes
$STD php asatru calendar:classes
ADMIN_EMAIL="admin@example.com"
ADMIN_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)"
ADMIN_HASH=$(php -r "echo password_hash('$ADMIN_PASS', PASSWORD_BCRYPT);")
$STD mariadb -u root -D $DB_NAME -e "INSERT IGNORE INTO UserModel (name, email, password, admin) VALUES ('Admin', '$ADMIN_EMAIL', '$ADMIN_HASH', 1);"
$STD mariadb -u root -D $MARIADB_DB_NAME -e "INSERT IGNORE INTO UserModel (name, email, password, admin) VALUES ('Admin', '$ADMIN_EMAIL', '$ADMIN_HASH', 1);"
{
echo ""
echo "HortusFox-Admin-Creds:"
echo "E-Mail: $ADMIN_EMAIL"
echo "Passwort: $ADMIN_PASS"
} >>~/hortusfox.creds
$STD mariadb -u root -D $DB_NAME -e "INSERT IGNORE INTO LocationsModel (name, active, created_at) VALUES ('Home', 1, NOW());"
$STD mariadb -u root -D $MARIADB_DB_NAME -e "INSERT IGNORE INTO LocationsModel (name, active, created_at) VALUES ('Home', 1, NOW());"
msg_ok "Set up HortusFox"
msg_info "Configuring Apache vHost"

View File

@@ -16,11 +16,12 @@ update_os
msg_info "Installing Dependencies"
$STD apt install -y \
apt-transport-https \
ca-certificates \
redis
msg_ok "Installed Dependencies"
PG_VERSION="17" setup_postgresql
PG_DB_NAME="infisical_db" PG_DB_USER="infisical" setup_postgresql_db
import_local_ip
msg_info "Setting up Infisical Repository"
setup_deb822_repo \
@@ -30,34 +31,16 @@ setup_deb822_repo \
"stable"
msg_ok "Setup Infisical repository"
msg_info "Configuring PostgreSQL"
DB_NAME="infisical_db"
DB_USER="infisical"
DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)"
$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';"
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';"
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';"
$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';"
{
echo "Infiscal Credentials"
echo "Database Name: $DB_NAME"
echo "Database User: $DB_USER"
echo "Database Password: $DB_PASS"
} >>~/infisical.creds
msg_ok "Configured PostgreSQL"
msg_info "Setting up Infisical"
AUTH_SECRET="$(openssl rand -base64 32 | tr -d '\n')"
ENC_KEY="$(openssl rand -hex 16 | tr -d '\n')"
IP_ADDR=$(hostname -I | awk '{print $1}')
$STD apt install -y infisical-core
mkdir -p /etc/infisical
cat <<EOF >/etc/infisical/infisical.rb
infisical_core['ENCRYPTION_KEY'] = '$ENC_KEY'
infisical_core['AUTH_SECRET'] = '$AUTH_SECRET'
infisical_core['HOST'] = '$IP_ADDR'
infisical_core['DB_CONNECTION_URI'] = 'postgres://${DB_USER}:${DB_PASS}@localhost:5432/${DB_NAME}'
infisical_core['HOST'] = '$LOCAL_IP'
infisical_core['DB_CONNECTION_URI'] = 'postgres://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}'
infisical_core['REDIS_URL'] = 'redis://localhost:6379'
EOF
$STD infisical-ctl reconfigure

View File

@@ -21,23 +21,29 @@ setup_deb822_repo \
"stable"
msg_ok "Set up InfluxDB Repository"
read -r -p "${TAB3}Which version of InfluxDB to install? (1 or 2) " prompt
if [[ $prompt == "2" ]]; then
read -r -p "${TAB3}Which version of InfluxDB to install? (1, 2 or 3) " prompt
if [[ $prompt == "3" ]]; then
INFLUX="3"
elif [[ $prompt == "2" ]]; then
INFLUX="2"
else
INFLUX="1"
fi
msg_info "Installing InfluxDB"
if [[ $INFLUX == "2" ]]; then
msg_info "Installing InfluxDB v${INFLUX}"
if [[ $INFLUX == "3" ]]; then
$STD apt install -y influxdb3-core
systemctl enable -q --now influxdb3-core
elif [[ $INFLUX == "2" ]]; then
$STD apt install -y influxdb2
systemctl enable -q --now influxdb
else
$STD apt install -y influxdb
download_file "https://dl.influxdata.com/chronograf/releases/chronograf_1.10.8_amd64.deb" "${HOME}/chronograf_1.10.8_amd64.deb"
$STD dpkg -i "${HOME}/chronograf_1.10.8_amd64.deb"
rm -rf "${HOME}/chronograf_1.10.8_amd64.deb"
systemctl enable -q --now influxdb
fi
systemctl enable -q --now influxdb
msg_ok "Installed InfluxDB"
read -r -p "${TAB3}Would you like to add Telegraf? <y/N> " prompt

View File

@@ -106,6 +106,7 @@ $STD php artisan migrate --force
$STD php artisan db:seed --force
$STD php artisan ninja:post-update
$STD php artisan optimize
chown -R www-data:www-data /opt/invoiceninja
msg_ok "Set up Database"
msg_info "Configuring Nginx"

View File

@@ -13,11 +13,14 @@ network_check
update_os
JAVA_VERSION="21" setup_java
setup_deb822_repo \
"jenkins" \
"https://pkg.jenkins.io/debian/jenkins.io-2026.key" \
"https://pkg.jenkins.io/debian" \
"binary/" \
" "
msg_info "Setup Jenkins"
curl -fsSL "https://pkg.jenkins.io/debian/jenkins.io-2023.key" -o "/usr/share/keyrings/jenkins-keyring.asc"
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" https://pkg.jenkins.io/debian binary/ >/etc/apt/sources.list.d/jenkins.list
$STD apt update
$STD apt install -y jenkins
msg_ok "Setup Jenkins"

View File

@@ -24,8 +24,8 @@ msg_info "Configuring monica"
cd /opt/monica
cp /opt/monica/.env.example /opt/monica/.env
HASH_SALT=$(openssl rand -base64 32)
sed -i -e "s|^DB_USERNAME=.*|DB_USERNAME=${DB_USER}|" \
-e "s|^DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" \
sed -i -e "s|^DB_USERNAME=.*|DB_USERNAME=${MARIADB_DB_USER}|" \
-e "s|^DB_PASSWORD=.*|DB_PASSWORD=${MARIADB_DB_PASS}|" \
-e "s|^HASH_SALT=.*|HASH_SALT=${HASH_SALT}|" \
/opt/monica/.env
$STD composer install --no-dev -o --no-interaction

View File

@@ -20,7 +20,7 @@ $STD apt install -y \
redis
msg_ok "Installed Dependencies"
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
NODE_VERSION="22" setup_nodejs
PG_VERSION="16" setup_postgresql
PG_DB_NAME="outline" PG_DB_USER="outline" setup_postgresql_db
fetch_and_deploy_gh_release "outline" "outline/outline" "tarball"
@@ -38,7 +38,8 @@ sed -i 's/redis:6379/localhost:6379/g' /opt/outline/.env
sed -i "5s#URL=#URL=http://${LOCAL_IP}#g" /opt/outline/.env
sed -i 's/FORCE_HTTPS=true/FORCE_HTTPS=false/g' /opt/outline/.env
export NODE_OPTIONS="--max-old-space-size=3584"
$STD yarn install --frozen-lockfile
$STD corepack enable
$STD yarn install --immutable
export NODE_ENV=production
sed -i 's/NODE_ENV=development/NODE_ENV=production/g' /opt/outline/.env
$STD yarn build

View File

@@ -37,7 +37,7 @@ mkdir -p ./src/server/public
cp -r ./geo ./src/server/public
$STD pnpm build:server
cat <<EOF >/opt/tianji/src/server/.env
DATABASE_URL="postgresql://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME?schema=public"
DATABASE_URL="postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME?schema=public"
OPENAI_API_KEY=""
JWT_SECRET="$TIANJI_SECRET"
EOF

View File

@@ -231,6 +231,100 @@ install_ssh_keys_into_ct() {
return 0
}
# ------------------------------------------------------------------------------
# validate_container_id()
#
# - Validates if a container ID is available for use
# - Checks if ID is already used by VM or LXC container
# - Checks if ID is used in LVM logical volumes
# - Returns 0 if ID is available, 1 if already in use
# ------------------------------------------------------------------------------
validate_container_id() {
local ctid="$1"
# Check if ID is numeric
if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then
return 1
fi
# Check if config file exists for VM or LXC
if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then
return 1
fi
# Check if ID is used in LVM logical volumes
if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
# get_valid_container_id()
#
# - Returns a valid, unused container ID
# - If provided ID is valid, returns it
# - Otherwise increments from suggested ID until a free one is found
# - Calls validate_container_id() to check availability
# ------------------------------------------------------------------------------
get_valid_container_id() {
local suggested_id="${1:-$(pvesh get /cluster/nextid)}"
while ! validate_container_id "$suggested_id"; do
suggested_id=$((suggested_id + 1))
done
echo "$suggested_id"
}
# ------------------------------------------------------------------------------
# validate_container_id()
#
# - Validates if a container ID is available for use
# - Checks if ID is already used by VM or LXC container
# - Checks if ID is used in LVM logical volumes
# - Returns 0 if ID is available, 1 if already in use
# ------------------------------------------------------------------------------
validate_container_id() {
local ctid="$1"
# Check if ID is numeric
if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then
return 1
fi
# Check if config file exists for VM or LXC
if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then
return 1
fi
# Check if ID is used in LVM logical volumes
if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
# get_valid_container_id()
#
# - Returns a valid, unused container ID
# - If provided ID is valid, returns it
# - Otherwise increments from suggested ID until a free one is found
# - Calls validate_container_id() to check availability
# ------------------------------------------------------------------------------
get_valid_container_id() {
local suggested_id="${1:-$(pvesh get /cluster/nextid)}"
while ! validate_container_id "$suggested_id"; do
suggested_id=$((suggested_id + 1))
done
echo "$suggested_id"
}
# ------------------------------------------------------------------------------
# find_host_ssh_keys()
#
@@ -417,6 +511,12 @@ choose_and_set_storage_for_file() {
if [[ "$count" -eq 1 ]]; then
STORAGE_RESULT=$(pvesm status -content "$content" | awk 'NR>1{print $1; exit}')
STORAGE_INFO=""
# Validate storage space for auto-picked container storage
if [[ "$class" == "container" && -n "${DISK_SIZE:-}" ]]; then
validate_storage_space "$STORAGE_RESULT" "$DISK_SIZE" "yes"
# Continue even if validation fails - user was warned
fi
else
# If the current value is preselectable, we could show it, but per your requirement we always offer selection
select_storage "$class" || return 1
@@ -483,7 +583,18 @@ base_settings() {
RAM_SIZE="${final_ram}"
VERBOSE=${var_verbose:-"${1:-no}"}
PW=${var_pw:-""}
CT_ID=${var_ctid:-$NEXTID}
# Validate and set Container ID
local requested_id="${var_ctid:-$NEXTID}"
if ! validate_container_id "$requested_id"; then
# Only show warning if user manually specified an ID (not auto-assigned)
if [[ -n "${var_ctid:-}" ]]; then
msg_warn "Container ID $requested_id is already in use. Using next available ID: $(get_valid_container_id "$requested_id")"
fi
requested_id=$(get_valid_container_id "$requested_id")
fi
CT_ID="$requested_id"
HN=${var_hostname:-$NSAPP}
BRG=${var_brg:-"vmbr0"}
NET=${var_net:-"dhcp"}
@@ -1098,6 +1209,13 @@ ensure_storage_selection_for_vars_file() {
if [[ -n "$tpl" && -n "$ct" ]]; then
TEMPLATE_STORAGE="$tpl"
CONTAINER_STORAGE="$ct"
# Validate storage space for loaded container storage
if [[ -n "${DISK_SIZE:-}" ]]; then
validate_storage_space "$ct" "$DISK_SIZE" "yes"
# Continue even if validation fails - user was warned
fi
return 0
fi
@@ -1308,7 +1426,25 @@ advanced_settings() {
--ok-button "Next" --cancel-button "Back" \
--inputbox "\nSet Container ID" 10 58 "$_ct_id" \
3>&1 1>&2 2>&3); then
_ct_id="${result:-$NEXTID}"
local input_id="${result:-$NEXTID}"
# Validate that ID is numeric
if ! [[ "$input_id" =~ ^[0-9]+$ ]]; then
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Invalid ID" --msgbox "Container ID must be numeric." 8 58
continue
fi
# Check if ID is already in use
if ! validate_container_id "$input_id"; then
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "ID Already In Use" \
--yesno "Container/VM ID $input_id is already in use.\n\nWould you like to use the next available ID ($(get_valid_container_id "$input_id"))?" 10 58; then
_ct_id=$(get_valid_container_id "$input_id")
else
continue
fi
else
_ct_id="$input_id"
fi
((STEP++))
else
((STEP--))
@@ -2292,7 +2428,6 @@ install_script() {
2 | advanced | ADVANCED)
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Install on node $PVEHOST_NAME${CL}"
echo -e "${INFO}${BOLD}${DGN}PVE Version ${PVEVERSION} (Kernel: ${KERNEL_VERSION})${CL}"
METHOD="advanced"
base_settings
advanced_settings
@@ -2853,6 +2988,21 @@ $PCT_OPTIONS_STRING"
export TEMPLATE_STORAGE="${var_template_storage:-}"
export CONTAINER_STORAGE="${var_container_storage:-}"
# Validate storage space only if CONTAINER_STORAGE is already set
# (Storage selection happens in create_lxc_container for some modes)
if [[ -n "$CONTAINER_STORAGE" ]]; then
msg_info "Validating storage space"
if ! validate_storage_space "$CONTAINER_STORAGE" "$DISK_SIZE" "no"; then
local free_space
free_space=$(pvesm status 2>/dev/null | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
local free_fmt
free_fmt=$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$free_space" 2>/dev/null || echo "${free_space}KB")
msg_error "Not enough space on '$CONTAINER_STORAGE'. Required: ${DISK_SIZE}GB, Available: ${free_fmt}"
exit 214
fi
msg_ok "Storage space validated"
fi
create_lxc_container || exit $?
LXC_CONFIG="/etc/pve/lxc/${CTID}.conf"
@@ -3384,9 +3534,9 @@ resolve_storage_preselect() {
free="$(awk '{print $6}' <<<"$line")"
local total_h used_h free_h
if command -v numfmt >/dev/null 2>&1; then
total_h="$(numfmt --to=iec --suffix=B --format %.1f "$total" 2>/dev/null || echo "$total")"
used_h="$(numfmt --to=iec --suffix=B --format %.1f "$used" 2>/dev/null || echo "$used")"
free_h="$(numfmt --to=iec --suffix=B --format %.1f "$free" 2>/dev/null || echo "$free")"
total_h="$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$total" 2>/dev/null || echo "$total")"
used_h="$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$used" 2>/dev/null || echo "$used")"
free_h="$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$free" 2>/dev/null || echo "$free")"
STORAGE_INFO="Free: ${free_h} Used: ${used_h}"
else
STORAGE_INFO="Free: ${free} Used: ${used}"
@@ -3502,8 +3652,8 @@ select_storage() {
while read -r TAG TYPE _ TOTAL USED FREE _; do
[[ -n "$TAG" && -n "$TYPE" ]] || continue
local DISPLAY="${TAG} (${TYPE})"
local USED_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$USED")
local FREE_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$FREE")
local USED_FMT=$(numfmt --to=iec --from-unit=1024 --format %.1f <<<"$USED")
local FREE_FMT=$(numfmt --to=iec --from-unit=1024 --format %.1f <<<"$FREE")
local INFO="Free: ${FREE_FMT}B Used: ${USED_FMT}B"
STORAGE_MAP["$DISPLAY"]="$TAG"
MENU+=("$DISPLAY" "$INFO" "OFF")
@@ -3541,10 +3691,87 @@ select_storage() {
break
fi
done
# Validate storage space for container storage
if [[ "$CLASS" == "container" && -n "${DISK_SIZE:-}" ]]; then
validate_storage_space "$STORAGE_RESULT" "$DISK_SIZE" "yes"
# Continue even if validation fails - user was warned
fi
return 0
done
}
# ------------------------------------------------------------------------------
# validate_storage_space()
#
# - Validates if storage has enough free space for container
# - Takes storage name and required size in GB
# - Returns 0 if enough space, 1 if not enough, 2 if storage unavailable
# - Can optionally show whiptail warning
# - Handles all storage types: dir, lvm, lvmthin, zfs, nfs, cifs, etc.
# ------------------------------------------------------------------------------
validate_storage_space() {
local storage="$1"
local required_gb="${2:-8}"
local show_dialog="${3:-no}"
# Get full storage line from pvesm status
local storage_line
storage_line=$(pvesm status 2>/dev/null | awk -v s="$storage" '$1 == s {print $0}')
# Check if storage exists and is active
if [[ -z "$storage_line" ]]; then
[[ "$show_dialog" == "yes" ]] && whiptail --msgbox "⚠️ Warning: Storage '$storage' not found!\n\nThe storage may be unavailable or disabled." 10 60
return 2
fi
# Check storage status (column 3)
local status
status=$(awk '{print $3}' <<<"$storage_line")
if [[ "$status" == "disabled" ]]; then
[[ "$show_dialog" == "yes" ]] && whiptail --msgbox "⚠️ Warning: Storage '$storage' is disabled!\n\nPlease enable the storage first." 10 60
return 2
fi
# Get storage type and free space (column 6)
local storage_type storage_free
storage_type=$(awk '{print $2}' <<<"$storage_line")
storage_free=$(awk '{print $6}' <<<"$storage_line")
# Some storage types (like PBS, iSCSI) don't report size info
# In these cases, skip space validation
if [[ -z "$storage_free" || "$storage_free" == "0" ]]; then
# Silent pass for storages without size info
return 0
fi
local required_kb=$((required_gb * 1024 * 1024))
local free_gb_fmt
free_gb_fmt=$(numfmt --to=iec --from-unit=1024 --suffix=B --format %.1f "$storage_free" 2>/dev/null || echo "${storage_free}KB")
if [[ "$storage_free" -lt "$required_kb" ]]; then
if [[ "$show_dialog" == "yes" ]]; then
whiptail --msgbox "⚠️ Warning: Storage '$storage' may not have enough space!\n\nStorage Type: ${storage_type}\nRequired: ${required_gb}GB\nAvailable: ${free_gb_fmt}\n\nYou can continue, but creation might fail." 14 70
fi
return 1
fi
return 0
}
# ==============================================================================
# SECTION 8: CONTAINER CREATION
# ==============================================================================
# ------------------------------------------------------------------------------
# create_lxc_container()
#
# - Main function for creating LXC containers
# - Handles all phases: validation, template discovery, container creation,
# network config, storage, etc.
# - Extensive error checking with detailed exit codes
# ------------------------------------------------------------------------------
create_lxc_container() {
# ------------------------------------------------------------------------------
# Optional verbose mode (debug tracing)
@@ -3716,14 +3943,6 @@ create_lxc_container() {
fi
msg_ok "Template storage '$TEMPLATE_STORAGE' validated"
# Free space check
STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
REQUIRED_KB=$((${PCT_DISK_SIZE:-8} * 1024 * 1024))
[[ "$STORAGE_FREE" -ge "$REQUIRED_KB" ]] || {
msg_error "Not enough space on '$CONTAINER_STORAGE'. Needed: ${PCT_DISK_SIZE:-8}G."
exit 214
}
# Cluster quorum (if cluster)
if [[ -f /etc/pve/corosync.conf ]]; then
msg_info "Checking cluster quorum"

View File

@@ -184,7 +184,10 @@ install_packages_with_retry() {
local retry=0
while [[ $retry -le $max_retries ]]; do
if $STD apt install -y "${packages[@]}" 2>/dev/null; then
if DEBIAN_FRONTEND=noninteractive $STD apt install -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
"${packages[@]}" 2>/dev/null; then
return 0
fi
@@ -211,7 +214,10 @@ upgrade_packages_with_retry() {
local retry=0
while [[ $retry -le $max_retries ]]; do
if $STD apt install --only-upgrade -y "${packages[@]}" 2>/dev/null; then
if DEBIAN_FRONTEND=noninteractive $STD apt install --only-upgrade -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
"${packages[@]}" 2>/dev/null; then
return 0
fi
@@ -2920,8 +2926,15 @@ _setup_intel_legacy() {
vainfo \
intel-gpu-tools 2>/dev/null || msg_warn "Some Intel legacy packages failed"
# beignet provides OpenCL for older Intel GPUs (if available)
$STD apt -y install beignet-opencl-icd 2>/dev/null || true
# beignet provides OpenCL for older Intel GPUs (Sandy Bridge to Broadwell)
# Note: beignet-opencl-icd was removed in Debian 12+ and Ubuntu 22.04+
# Check if package is available before attempting installation
if apt-cache show beignet-opencl-icd &>/dev/null; then
$STD apt -y install beignet-opencl-icd 2>/dev/null || msg_warn "beignet-opencl-icd installation failed (optional)"
else
msg_warn "beignet-opencl-icd not available - OpenCL support for legacy Intel GPU limited"
msg_warn "Note: Hardware video encoding/decoding (VA-API) still works without OpenCL"
fi
msg_ok "Intel Legacy GPU configured"
}
@@ -3563,6 +3576,11 @@ EOF
setup_mariadb() {
local MARIADB_VERSION="${MARIADB_VERSION:-latest}"
# Ensure non-interactive mode for all apt operations
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1
# Resolve "latest" to actual version
if [[ "$MARIADB_VERSION" == "latest" ]]; then
if ! curl -fsI --max-time 10 http://mirror.mariadb.org/repo/ >/dev/null 2>&1; then
@@ -3601,6 +3619,20 @@ setup_mariadb() {
local CURRENT_VERSION=""
CURRENT_VERSION=$(is_tool_installed "mariadb" 2>/dev/null) || true
# Pre-configure debconf to prevent any interactive prompts during install/upgrade
local MARIADB_MAJOR_MINOR
MARIADB_MAJOR_MINOR=$(echo "$MARIADB_VERSION" | awk -F. '{print $1"."$2}')
if [[ -n "$MARIADB_MAJOR_MINOR" ]]; then
debconf-set-selections <<EOF
mariadb-server-$MARIADB_MAJOR_MINOR mariadb-server/feedback boolean false
mariadb-server-$MARIADB_MAJOR_MINOR mariadb-server/root_password password
mariadb-server-$MARIADB_MAJOR_MINOR mariadb-server/root_password_again password
mariadb-server mariadb-server/feedback boolean false
mariadb-server mariadb-server/root_password password
mariadb-server mariadb-server/root_password_again password
EOF
fi
# Scenario 1: Already installed at target version - just update packages
if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" == "$MARIADB_VERSION" ]]; then
msg_info "Update MariaDB $MARIADB_VERSION"
@@ -3667,15 +3699,7 @@ setup_mariadb() {
return 1
}
# Set debconf selections for all potential versions
local MARIADB_MAJOR_MINOR
MARIADB_MAJOR_MINOR=$(echo "$MARIADB_VERSION" | awk -F. '{print $1"."$2}')
if [[ -n "$MARIADB_MAJOR_MINOR" ]]; then
echo "mariadb-server-$MARIADB_MAJOR_MINOR mariadb-server/feedback boolean false" | debconf-set-selections
fi
# Install packages with retry logic
export DEBIAN_FRONTEND=noninteractive
if ! install_packages_with_retry "mariadb-server" "mariadb-client"; then
# Fallback: try without specific version
msg_warn "Failed to install MariaDB packages from upstream repo, trying distro fallback..."
@@ -3815,6 +3839,11 @@ function setup_mongodb() {
DISTRO_ID=$(get_os_info id)
DISTRO_CODENAME=$(get_os_info codename)
# Ensure non-interactive mode for all apt operations
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1
# Check AVX support
if ! grep -qm1 'avx[^ ]*' /proc/cpuinfo; then
local major="${MONGO_VERSION%%.*}"
@@ -3933,6 +3962,11 @@ function setup_mysql() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
# Ensure non-interactive mode for all apt operations
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1
# Get currently installed version
local CURRENT_VERSION=""
CURRENT_VERSION=$(is_tool_installed "mysql" 2>/dev/null) || true
@@ -4027,7 +4061,6 @@ EOF
ensure_apt_working || return 1
# Try multiple package names with retry logic
export DEBIAN_FRONTEND=noninteractive
local mysql_install_success=false
if apt-cache search "^mysql-server$" 2>/dev/null | grep -q . &&
@@ -4466,6 +4499,11 @@ function setup_postgresql() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
# Ensure non-interactive mode for all apt operations
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1
# Get currently installed version
local CURRENT_PG_VERSION=""
if command -v psql >/dev/null; then
@@ -4923,6 +4961,11 @@ function setup_clickhouse() {
DISTRO_ID=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"')
DISTRO_CODENAME=$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)
# Ensure non-interactive mode for all apt operations
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
export NEEDRESTART_SUSPEND=1
# Resolve "latest" version
if [[ "$CLICKHOUSE_VERSION" == "latest" ]]; then
CLICKHOUSE_VERSION=$(curl -fsSL --max-time 15 https://packages.clickhouse.com/tgz/stable/ 2>/dev/null |
@@ -4985,7 +5028,6 @@ function setup_clickhouse() {
"main"
# Install packages with retry logic
export DEBIAN_FRONTEND=noninteractive
$STD apt update || {
msg_error "APT update failed for ClickHouse repository"
return 1

View File

@@ -42,6 +42,29 @@ function msg() {
local TEXT="$1"
echo -e "$TEXT"
}
function validate_container_id() {
local ctid="$1"
# Check if ID is numeric
if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then
return 1
fi
# Check if config file exists for VM or LXC
if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then
return 1
fi
# Check if ID is used in LVM logical volumes
if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then
return 1
fi
return 0
}
function get_valid_container_id() {
local suggested_id="${1:-$(pvesh get /cluster/nextid)}"
while ! validate_container_id "$suggested_id"; do
suggested_id=$((suggested_id + 1))
done
echo "$suggested_id"
}
function cleanup_ctid() {
if pct status $CTID &>/dev/null; then
if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then
@@ -76,7 +99,15 @@ TEMPLATE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templat
# Setup script environment
NAME=$(echo "$TEMPLATE" | grep -oE '^[^-]+-[^-]+')
PASS="$(openssl rand -base64 8)"
# Get valid Container ID
CTID=$(pvesh get /cluster/nextid)
if ! validate_container_id "$CTID"; then
warn "Container ID $CTID is already in use."
CTID=$(get_valid_container_id "$CTID")
info "Using next available ID: $CTID"
fi
PCT_OPTIONS="
-features keyctl=1,nesting=1
-hostname $NAME

369
tools/addon/jellystat.sh Normal file
View File

@@ -0,0 +1,369 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/CyferShepard/Jellystat
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)
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# ==============================================================================
# CONFIGURATION
# ==============================================================================
APP="Jellystat"
APP_TYPE="addon"
INSTALL_PATH="/opt/jellystat"
CONFIG_PATH="/opt/jellystat/.env"
DEFAULT_PORT=3000
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
__ ____ __ __
/ /__ / / /_ _______/ /_____ _/ /_
__ / / _ \/ / / / / / ___/ __/ __ `/ __/
/ /_/ / __/ / / /_/ (__ ) /_/ /_/ / /_
\____/\___/_/_/\__, /____/\__/\__,_/\__/
/____/
EOF
}
# ==============================================================================
# OS DETECTION
# ==============================================================================
if [[ -f "/etc/alpine-release" ]]; then
msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
exit 1
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
fi
# ==============================================================================
# UNINSTALL
# ==============================================================================
function uninstall() {
msg_info "Uninstalling ${APP}"
systemctl disable --now jellystat.service &>/dev/null || true
rm -f "$SERVICE_PATH"
rm -rf "$INSTALL_PATH"
rm -f "/usr/local/bin/update_jellystat"
rm -f "$HOME/.jellystat"
msg_ok "${APP} has been uninstalled"
# Ask about PostgreSQL database removal
echo ""
echo -n "${TAB}Also remove PostgreSQL database 'jellystat'? (y/N): "
read -r db_prompt
if [[ "${db_prompt,,}" =~ ^(y|yes)$ ]]; then
if command -v psql &>/dev/null; then
msg_info "Removing PostgreSQL database and user"
$STD sudo -u postgres psql -c "DROP DATABASE IF EXISTS jellystat;" &>/dev/null || true
$STD sudo -u postgres psql -c "DROP USER IF EXISTS jellystat;" &>/dev/null || true
msg_ok "Removed PostgreSQL database 'jellystat' and user 'jellystat'"
else
msg_warn "PostgreSQL not found - database may have been removed already"
fi
else
msg_warn "PostgreSQL database was NOT removed. Remove manually if needed:"
echo -e "${TAB} sudo -u postgres psql -c \"DROP DATABASE jellystat;\""
echo -e "${TAB} sudo -u postgres psql -c \"DROP USER jellystat;\""
fi
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
if check_for_gh_release "jellystat" "CyferShepard/Jellystat"; then
msg_info "Stopping service"
systemctl stop jellystat.service &>/dev/null || true
msg_ok "Stopped service"
msg_info "Backing up configuration"
cp "$CONFIG_PATH" /tmp/jellystat.env.bak 2>/dev/null || true
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
msg_info "Restoring configuration"
cp /tmp/jellystat.env.bak "$CONFIG_PATH" 2>/dev/null || true
rm -f /tmp/jellystat.env.bak
msg_ok "Restored configuration"
msg_info "Installing dependencies"
cd "$INSTALL_PATH"
$STD npm install
msg_ok "Installed dependencies"
msg_info "Building ${APP}"
$STD npm run build
msg_ok "Built ${APP}"
msg_info "Starting service"
systemctl start jellystat
msg_ok "Started service"
msg_ok "Updated successfully"
exit
fi
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
# Setup Node.js (only installs if not present or different version)
if command -v node &>/dev/null; then
msg_ok "Node.js already installed ($(node -v))"
else
NODE_VERSION="22" setup_nodejs
fi
# Setup PostgreSQL (only installs if not present)
if command -v psql &>/dev/null; then
msg_ok "PostgreSQL already installed"
else
PG_VERSION="17" setup_postgresql
fi
# Create database and user (skip if already exists)
local DB_NAME="jellystat"
local DB_USER="jellystat"
local DB_PASS
msg_info "Setting up PostgreSQL database"
# Check if database already exists
if sudo -u postgres psql -lqt 2>/dev/null | cut -d \| -f 1 | grep -qw "$DB_NAME"; then
msg_warn "Database '${DB_NAME}' already exists - skipping creation"
echo -n "${TAB}Enter existing database password for '${DB_USER}': "
read -rs DB_PASS
echo ""
else
# Generate new password
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c16)
# Check if user exists, create if not
if sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" 2>/dev/null | grep -q 1; then
msg_info "User '${DB_USER}' exists, updating password"
$STD sudo -u postgres psql -c "ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASS}';" || {
msg_error "Failed to update PostgreSQL user"
return 1
}
else
$STD sudo -u postgres psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}';" || {
msg_error "Failed to create PostgreSQL user"
return 1
}
fi
# Create database (use template0 for UTF8 encoding compatibility)
$STD sudo -u postgres psql -c "CREATE DATABASE ${DB_NAME} WITH OWNER ${DB_USER} ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0;" || {
msg_error "Failed to create PostgreSQL database"
return 1
}
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};" || {
msg_error "Failed to grant privileges"
return 1
}
# Grant schema permissions (required for PostgreSQL 15+)
$STD sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO ${DB_USER};" || true
# Configure pg_hba.conf for password authentication on localhost
local PG_HBA
PG_HBA=$(sudo -u postgres psql -tAc "SHOW hba_file;" 2>/dev/null | tr -d ' ')
if [[ -n "$PG_HBA" && -f "$PG_HBA" ]]; then
# Check if md5/scram-sha-256 auth is already configured for local connections
if ! grep -qE "^host\s+${DB_NAME}\s+${DB_USER}\s+127.0.0.1" "$PG_HBA"; then
msg_info "Configuring PostgreSQL authentication"
# Add password auth for jellystat user on localhost (before the default rules)
sed -i "/^# IPv4 local connections:/a host ${DB_NAME} ${DB_USER} 127.0.0.1/32 scram-sha-256" "$PG_HBA"
sed -i "/^# IPv4 local connections:/a host ${DB_NAME} ${DB_USER} ::1/128 scram-sha-256" "$PG_HBA"
# Reload PostgreSQL to apply changes
systemctl reload postgresql
msg_ok "Configured PostgreSQL authentication"
fi
fi
msg_ok "Created PostgreSQL database '${DB_NAME}'"
fi
# Generate JWT Secret
local JWT_SECRET
JWT_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
# Force fresh download by removing version cache
rm -f "$HOME/.jellystat"
fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
msg_info "Installing dependencies"
cd "$INSTALL_PATH"
$STD npm install
msg_ok "Installed dependencies"
msg_info "Building ${APP}"
$STD npm run build
msg_ok "Built ${APP}"
msg_info "Creating configuration"
cat <<EOF >"$CONFIG_PATH"
# Jellystat Configuration
# Database
POSTGRES_USER=${DB_USER}
POSTGRES_PASSWORD=${DB_PASS}
POSTGRES_IP=localhost
POSTGRES_PORT=5432
POSTGRES_DB=${DB_NAME}
# Security
JWT_SECRET=${JWT_SECRET}
# Server
JS_LISTEN_IP=0.0.0.0
JS_BASE_URL=/
TZ=$(cat /etc/timezone 2>/dev/null || echo "UTC")
# Optional: GeoLite for IP Geolocation
# JS_GEOLITE_ACCOUNT_ID=
# JS_GEOLITE_LICENSE_KEY=
# Optional: Master Override (if you forget your password)
# JS_USER=admin
# JS_PASSWORD=admin
# Optional: Minimum playback duration to record (seconds)
# MINIMUM_SECONDS_TO_INCLUDE_PLAYBACK=1
# Optional: Self-signed certificates
REJECT_SELF_SIGNED_CERTIFICATES=true
EOF
chmod 600 "$CONFIG_PATH"
msg_ok "Created configuration"
msg_info "Creating service"
cat <<EOF >"$SERVICE_PATH"
[Unit]
Description=Jellystat - Statistics for Jellyfin
After=network.target postgresql.service
[Service]
Type=simple
User=root
WorkingDirectory=${INSTALL_PATH}
EnvironmentFile=${CONFIG_PATH}
ExecStart=/usr/bin/node ${INSTALL_PATH}/backend/server.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now jellystat &>/dev/null
msg_ok "Created and started service"
# Create update script (simple wrapper that calls this addon with type=update)
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_jellystat
#!/usr/bin/env bash
# Jellystat Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/jellystat.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_jellystat
msg_ok "Created update script (/usr/local/bin/update_jellystat)"
# Save credentials
local CREDS_FILE="/root/jellystat.creds"
cat <<EOF >"$CREDS_FILE"
Jellystat Credentials
=====================
Database User: ${DB_USER}
Database Password: ${DB_PASS}
Database Name: ${DB_NAME}
JWT Secret: ${JWT_SECRET}
Web UI: http://${LOCAL_IP}:${DEFAULT_PORT}
EOF
chmod 600 "$CREDS_FILE"
echo ""
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
msg_ok "Credentials saved to: ${BL}${CREDS_FILE}${CL}"
echo ""
msg_warn "On first access, you'll need to configure your Jellyfin server connection."
}
# ==============================================================================
# MAIN
# ==============================================================================
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/package.json" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
exit 1
fi
exit 0
fi
header_info
import_local_ip
# Check if already installed
if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/package.json" ]]; then
msg_warn "${APP} is already installed."
echo ""
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
fi
echo -n "${TAB}Update ${APP}? (y/N): "
read -r update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
update
exit 0
fi
msg_warn "No action selected. Exiting."
exit 0
fi
# Fresh installation
msg_warn "${APP} is not installed."
echo ""
echo -e "${TAB}${INFO} This will install:"
echo -e "${TAB} - Node.js 22"
echo -e "${TAB} - PostgreSQL 17"
echo -e "${TAB} - Jellystat"
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/jellystat Normal file
View File

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

View File

@@ -42,6 +42,29 @@ function msg() {
local TEXT="$1"
echo -e "$TEXT"
}
function validate_container_id() {
local ctid="$1"
# Check if ID is numeric
if ! [[ "$ctid" =~ ^[0-9]+$ ]]; then
return 1
fi
# Check if config file exists for VM or LXC
if [[ -f "/etc/pve/qemu-server/${ctid}.conf" ]] || [[ -f "/etc/pve/lxc/${ctid}.conf" ]]; then
return 1
fi
# Check if ID is used in LVM logical volumes
if lvs --noheadings -o lv_name 2>/dev/null | grep -qE "(^|[-_])${ctid}($|[-_])"; then
return 1
fi
return 0
}
function get_valid_container_id() {
local suggested_id="${1:-$(pvesh get /cluster/nextid)}"
while ! validate_container_id "$suggested_id"; do
suggested_id=$((suggested_id + 1))
done
echo "$suggested_id"
}
function cleanup_ctid() {
if pct status $CTID &>/dev/null; then
if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then
@@ -99,9 +122,26 @@ turnkey=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "TurnKey LXCs
# Setup script environment
PASS="$(openssl rand -base64 8)"
# Prompt user to confirm container ID
CTID=$(whiptail --backtitle "Container ID" --title "Choose the Container ID" --inputbox "Enter the conatiner ID..." 8 40 $(pvesh get /cluster/nextid) 3>&1 1>&2 2>&3)
while true; do
CTID=$(whiptail --backtitle "Container ID" --title "Choose the Container ID" --inputbox "Enter the container ID..." 8 40 $(pvesh get /cluster/nextid) 3>&1 1>&2 2>&3)
# Check if user cancelled
[ -z "$CTID" ] && die "No Container ID selected"
# Validate Container ID
if ! validate_container_id "$CTID"; then
SUGGESTED_ID=$(get_valid_container_id "$CTID")
if whiptail --backtitle "Container ID" --title "ID Already In Use" --yesno "Container/VM ID $CTID is already in use.\n\nWould you like to use the next available ID ($SUGGESTED_ID)?" 10 58; then
CTID="$SUGGESTED_ID"
break
fi
# User declined, loop back to input
else
break
fi
done
# Prompt user to confirm Hostname
HOST_NAME=$(whiptail --backtitle "Hostname" --title "Choose the Hostname" --inputbox "Enter the containers Hostname..." 8 40 "turnkey-${turnkey}" 3>&1 1>&2 2>&3)
HOST_NAME=$(whiptail --backtitle "Hostname" --title "Choose the Hostname" --inputbox "Enter the containers Hostname..." 8 40 "turnkey-${turnkey}" 3>&1 1>&2 2>&3)
PCT_OPTIONS="
-features keyctl=1,nesting=1
-hostname $HOST_NAME
@@ -206,8 +246,8 @@ echo "TurnKey ${turnkey} password: ${PASS}" >>~/turnkey-${turnkey}.creds # file
TUN_DEVICE_REQUIRED=("openvpn") # Setup this way in case future turnkeys also need tun access
if printf '%s\n' "${TUN_DEVICE_REQUIRED[@]}" | grep -qw "${turnkey}"; then
info "${turnkey} requires access to /dev/net/tun on the host. Modifying the container configuration to allow this."
echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >> /etc/pve/lxc/${CTID}.conf
echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0" >> /etc/pve/lxc/${CTID}.conf
echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >>/etc/pve/lxc/${CTID}.conf
echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0" >>/etc/pve/lxc/${CTID}.conf
sleep 5
fi

View File

@@ -93,20 +93,20 @@ function get_valid_nextid() {
}
function cleanup_vmid() {
if qm status "$VMID" &>/dev/null; then
qm stop "$VMID" &>/dev/null
qm destroy "$VMID" &>/dev/null
if qm status $VMID &>/dev/null; then
qm stop $VMID &>/dev/null
qm destroy $VMID &>/dev/null
fi
}
function cleanup() {
popd >/dev/null
post_update_to_api "done" "none"
rm -rf "$TEMP_DIR"
rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd "$TEMP_DIR" >/dev/null
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Arch Linux VM" --yesno "This will create a New Arch Linux VM. Proceed?" 10 58; then
:
else
@@ -494,14 +494,14 @@ for i in {0,1}; do
done
msg_info "Creating a Arch Linux VM"
qm create "$VMID" -agent 1"${MACHINE}" -tablet 0 -localtime 1 -bios ovmf"${CPU_TYPE}" -cores "$CORE_COUNT" -memory "$RAM_SIZE" \
-name "$HN" -tags community-script -net0 virtio,bridge="$BRG",macaddr="$MAC"$VLAN"$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc "$STORAGE" "$VMID" "$DISK0" 4M 1>&/dev/null
qm importdisk "$VMID" "${FILE}" "$STORAGE" "${DISK_IMPORT:-}" 1>&/dev/null
qm set "$VMID" \
-efidisk0 "${DISK0_REF}"${FORMAT} \
-scsi0 "${DISK1_REF}",${DISK_CACHE}${THIN}size="${DISK_SIZE}" \
-ide2 "${STORAGE}":cloudinit \
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
qm set $VMID \
-efidisk0 ${DISK0_REF}${FORMAT} \
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
-ide2 ${STORAGE}:cloudinit \
-boot order=scsi0 \
-serial0 socket >/dev/null
DESCRIPTION=$(
@@ -534,19 +534,19 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DEFAULT_DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Arch Linux VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
msg_info "Starting Arch Linux VM"
qm start "$VMID"
qm start $VMID
msg_ok "Started Arch Linux VM"
fi
post_update_to_api "done" "none"

View File

@@ -93,20 +93,20 @@ function get_valid_nextid() {
}
function cleanup_vmid() {
if qm status "$VMID" &>/dev/null; then
qm stop "$VMID" &>/dev/null
qm destroy "$VMID" &>/dev/null
if qm status $VMID &>/dev/null; then
qm stop $VMID &>/dev/null
qm destroy $VMID &>/dev/null
fi
}
function cleanup() {
popd >/dev/null
post_update_to_api "done" "none"
rm -rf "$TEMP_DIR"
rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd "$TEMP_DIR" >/dev/null
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 13 VM" --yesno "This will create a New Debian 13 VM. Proceed?" 10 58; then
:
else
@@ -509,21 +509,21 @@ for i in {0,1}; do
done
msg_info "Creating a Debian 13 VM"
qm create "$VMID" -agent 1"${MACHINE}" -tablet 0 -localtime 1 -bios ovmf"${CPU_TYPE}" -cores "$CORE_COUNT" -memory "$RAM_SIZE" \
-name "$HN" -tags community-script -net0 virtio,bridge="$BRG",macaddr="$MAC"$VLAN"$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc "$STORAGE" "$VMID" "$DISK0" 4M 1>&/dev/null
qm importdisk "$VMID" "${FILE}" "$STORAGE" "${DISK_IMPORT:-}" 1>&/dev/null
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
if [ "$CLOUD_INIT" == "yes" ]; then
qm set "$VMID" \
-efidisk0 "${DISK0_REF}"${FORMAT} \
-scsi0 "${DISK1_REF}",${DISK_CACHE}${THIN}size="${DISK_SIZE}" \
-scsi1 "${STORAGE}":cloudinit \
qm set $VMID \
-efidisk0 ${DISK0_REF}${FORMAT} \
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
-scsi1 ${STORAGE}:cloudinit \
-boot order=scsi0 \
-serial0 socket >/dev/null
else
qm set "$VMID" \
-efidisk0 "${DISK0_REF}"${FORMAT} \
-scsi0 "${DISK1_REF}",${DISK_CACHE}${THIN}size="${DISK_SIZE}" \
qm set $VMID \
-efidisk0 ${DISK0_REF}${FORMAT} \
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
-boot order=scsi0 \
-serial0 socket >/dev/null
fi
@@ -557,19 +557,19 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DEFAULT_DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Debian 13 VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
msg_info "Starting Debian 13 VM"
qm start "$VMID"
qm start $VMID
msg_ok "Started Debian 13 VM"
fi

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Copyright (c) 2021-2025 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -93,20 +93,20 @@ function get_valid_nextid() {
}
function cleanup_vmid() {
if qm status "$VMID" &>/dev/null; then
qm stop "$VMID" &>/dev/null
qm destroy "$VMID" &>/dev/null
if qm status $VMID &>/dev/null; then
qm stop $VMID &>/dev/null
qm destroy $VMID &>/dev/null
fi
}
function cleanup() {
popd >/dev/null
post_update_to_api "done" "none"
rm -rf "$TEMP_DIR"
rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d)
pushd "$TEMP_DIR" >/dev/null
pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Debian 12 VM" --yesno "This will create a New Debian 12 VM. Proceed?" 10 58; then
:
else
@@ -239,7 +239,7 @@ function advanced_settings() {
METHOD="advanced"
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
while true; do
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 "$VMID" --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VMID" ]; then
VMID=$(get_valid_nextid)
fi
@@ -259,7 +259,7 @@ function advanced_settings() {
"i440fx" "Machine i440fx" ON \
"q35" "Machine q35" OFF \
3>&1 1>&2 2>&3); then
if [ "$MACH" = q35 ]; then
if [ $MACH = q35 ]; then
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
FORMAT=""
MACHINE=" -machine q35"
@@ -291,7 +291,7 @@ function advanced_settings() {
"0" "None (Default)" ON \
"1" "Write Through" OFF \
3>&1 1>&2 2>&3); then
if [ "$DISK_CACHE" = "1" ]; then
if [ $DISK_CACHE = "1" ]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
DISK_CACHE="cache=writethrough,"
else
@@ -303,11 +303,11 @@ function advanced_settings() {
fi
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 debian --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VM_NAME" ]; then
if [ -z $VM_NAME ]; then
HN="debian"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
HN=$(echo "${VM_NAME,,}" | tr -d ' ')
HN=$(echo ${VM_NAME,,} | tr -d ' ')
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
fi
else
@@ -318,7 +318,7 @@ function advanced_settings() {
"0" "KVM64 (Default)" ON \
"1" "Host" OFF \
3>&1 1>&2 2>&3); then
if [ "$CPU_TYPE1" = "1" ]; then
if [ $CPU_TYPE1 = "1" ]; then
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
CPU_TYPE=" -cpu host"
else
@@ -330,7 +330,7 @@ function advanced_settings() {
fi
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$CORE_COUNT" ]; then
if [ -z $CORE_COUNT ]; then
CORE_COUNT="2"
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
else
@@ -341,7 +341,7 @@ function advanced_settings() {
fi
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$RAM_SIZE" ]; then
if [ -z $RAM_SIZE ]; then
RAM_SIZE="2048"
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
else
@@ -352,7 +352,7 @@ function advanced_settings() {
fi
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$BRG" ]; then
if [ -z $BRG ]; then
BRG="vmbr0"
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
else
@@ -362,8 +362,8 @@ function advanced_settings() {
exit-script
fi
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 "$GEN_MAC" --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MAC1" ]; then
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $MAC1 ]; then
MAC="$GEN_MAC"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
else
@@ -375,7 +375,7 @@ function advanced_settings() {
fi
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VLAN1" ]; then
if [ -z $VLAN1 ]; then
VLAN1="Default"
VLAN=""
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
@@ -388,7 +388,7 @@ function advanced_settings() {
fi
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MTU1" ]; then
if [ -z $MTU1 ]; then
MTU1="Default"
MTU=""
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
@@ -447,9 +447,9 @@ post_to_api_vm
msg_info "Validating Storage"
while read -r line; do
TAG=$(echo "$line" | awk '{print $1}')
TYPE=$(echo "$line" | awk '{printf "%-10s", $2}')
FREE=$(echo "$line" | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
TAG=$(echo $line | awk '{print $1}')
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
@@ -486,7 +486,7 @@ echo -en "\e[1A\e[0K"
FILE=$(basename $URL)
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
STORAGE_TYPE=$(pvesm status -storage "$STORAGE" | awk 'NR>1 {print $2}')
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
case $STORAGE_TYPE in
nfs | dir)
DISK_EXT=".qcow2"
@@ -504,26 +504,26 @@ btrfs)
esac
for i in {0,1}; do
disk="DISK$i"
eval DISK"${i}"=vm-"${VMID}"-disk-"${i}"${DISK_EXT:-}
eval DISK"${i}"_REF="${STORAGE}":"${DISK_REF:-}"${!disk}
eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
done
msg_info "Creating a Debian 12 VM"
qm create "$VMID" -agent 1"${MACHINE}" -tablet 0 -localtime 1 -bios ovmf"${CPU_TYPE}" -cores "$CORE_COUNT" -memory "$RAM_SIZE" \
-name "$HN" -tags community-script -net0 virtio,bridge="$BRG",macaddr="$MAC"$VLAN"$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc "$STORAGE" "$VMID" "$DISK0" 4M 1>&/dev/null
qm importdisk "$VMID" "${FILE}" "$STORAGE" "${DISK_IMPORT:-}" 1>&/dev/null
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
-name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
if [ "$CLOUD_INIT" == "yes" ]; then
qm set "$VMID" \
-efidisk0 "${DISK0_REF}"${FORMAT} \
-scsi0 "${DISK1_REF}",${DISK_CACHE}${THIN}size="${DISK_SIZE}" \
-scsi1 "${STORAGE}":cloudinit \
qm set $VMID \
-efidisk0 ${DISK0_REF}${FORMAT} \
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
-scsi1 ${STORAGE}:cloudinit \
-boot order=scsi0 \
-serial0 socket >/dev/null
else
qm set "$VMID" \
-efidisk0 "${DISK0_REF}"${FORMAT} \
-scsi0 "${DISK1_REF}",${DISK_CACHE}${THIN}size="${DISK_SIZE}" \
qm set $VMID \
-efidisk0 ${DISK0_REF}${FORMAT} \
-scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
-boot order=scsi0 \
-serial0 socket >/dev/null
fi
@@ -560,16 +560,16 @@ EOF
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
else
msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
qm resize "$VMID" scsi0 "${DEFAULT_DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
fi
msg_ok "Created a Debian 12 VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then
msg_info "Starting Debian 12 VM"
qm start "$VMID"
qm start $VMID
msg_ok "Started Debian 12 VM"
fi

View File

@@ -561,7 +561,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
msg_ok "Created a Docker VM ${CL}${BL}(${HN})"
if [ "$START_VM" == "yes" ]; then

View File

@@ -564,7 +564,7 @@ msg_ok "${CL}${BL}${URL}${CL}"
download_and_validate_xz "$URL" "$CACHE_FILE"
msg_info "Creating Home Assistant OS VM shell"
qm create "$VMID" -machine q35 -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
qm create $VMID -machine q35 -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
-cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" -tags community-script \
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
msg_ok "Created VM shell"
@@ -590,16 +590,16 @@ msg_ok "Imported disk (${CL}${BL}${DISK_REF}${CL})"
rm -f "$FILE_IMG"
msg_info "Attaching EFI and root disk"
qm set "$VMID" \
--efidisk0 "${STORAGE}:0,efitype=4m" \
--scsi0 "${DISK_REF},ssd=1,discard=on" \
qm set $VMID \
--efidisk0 ${STORAGE}:0,efitype=4m \
--scsi0 ${DISK_REF},ssd=1,discard=on \
--boot order=scsi0 \
--serial0 socket >/dev/null
qm set "$VMID" --agent enabled=1 >/dev/null
qm set $VMID --agent enabled=1 >/dev/null
msg_ok "Attached EFI and root disk"
msg_info "Resizing disk to $DISK_SIZE"
qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
msg_ok "Resized disk"
DESCRIPTION=$(
@@ -632,7 +632,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
msg_ok "Created Homeassistant OS VM ${CL}${BL}(${HN})"
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Image Cache" \

View File

@@ -274,11 +274,11 @@ function get_mikrotik_version() {
if [[ "$start_line" =~ ^[0-9]+$ ]]; then
local line
line=$(echo "$html" | tail -n +"$start_line" | grep -m 1 -E "c-(stable|longTerm|testing|development)-v|RouterOS [0-9]+\.[0-9]+" 2>/dev/null)
local version
version=$(echo "$line" | sed -n 's/.*c-[^"]*-v\([0-9_.a-zA-Z-]\+\).*/\1/p' | tr '_' '.' 2>/dev/null)
[ -z "$version" ] && version=$(echo "$line" | grep -oP 'RouterOS \K[0-9]+\.[0-9]+(\.[0-9]+)?' 2>/dev/null)
if [[ "$version" =~ ^[0-9]+\.[0-9]+ ]]; then
echo "$version"
return 0
@@ -611,7 +611,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -535,7 +535,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -528,16 +528,16 @@ FILE="${FILE%.*}"
msg_ok "Extracted OpenWrt Disk Image ${CL}${BL}$FILE${CL}"
msg_info "Creating OpenWrt VM"
qm create "$VMID" -cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" \
qm create $VMID -cores $CORE_COUNT -memory $RAM_SIZE -name $HN \
-onboot 1 -ostype l26 -scsihw virtio-scsi-pci --tablet 0
if [[ "$(pvesm status | awk -v s=$STORAGE '$1==s {print $2}')" == "dir" ]]; then
qm set "$VMID" -efidisk0 "${STORAGE}:0,efitype=4m,size=4M"
qm set $VMID -efidisk0 ${STORAGE}:0,efitype=4m,size=4M
else
pvesm alloc "$STORAGE" "$VMID" "vm-$VMID-disk-0" 4M >/dev/null
qm set "$VMID" -efidisk0 "${STORAGE}:vm-$VMID-disk-0,efitype=4m,size=4M"
pvesm alloc $STORAGE $VMID vm-$VMID-disk-0 4M >/dev/null
qm set $VMID -efidisk0 ${STORAGE}:vm-$VMID-disk-0,efitype=4m,size=4M
fi
IMPORT_OUT="$(qm importdisk "$VMID" "$FILE" "$STORAGE" --format raw 2>&1 || true)"
IMPORT_OUT="$(qm importdisk $VMID $FILE $STORAGE --format raw 2>&1 || true)"
DISK_REF="$(printf '%s\n' "$IMPORT_OUT" | sed -n "s/.*successfully imported disk '\([^']\+\)'.*/\1/p")"
if [[ -z "$DISK_REF" ]]; then
@@ -550,9 +550,9 @@ if [[ -z "$DISK_REF" ]]; then
exit 1
fi
qm set "$VMID" \
-efidisk0 "${STORAGE}:0,efitype=4m,size=4M" \
-scsi0 "${DISK_REF}" \
qm set $VMID \
-efidisk0 ${STORAGE}:0,efitype=4m,size=4M \
-scsi0 ${DISK_REF} \
-boot order=scsi0 \
-tags community-script >/dev/null
msg_ok "Attached disk"
@@ -591,7 +591,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
msg_ok "Created OpenWrt VM ${CL}${BL}(${HN})"
msg_info "OpenWrt is being started in order to configure the network interfaces."
@@ -636,14 +636,14 @@ done
msg_ok "OpenWrt has shut down"
msg_info "Adding bridge interfaces on Proxmox side"
qm set "$VMID" \
-net0 virtio,bridge="${LAN_BRG}",macaddr="${LAN_MAC}${LAN_VLAN}${MTU}" \
-net1 virtio,bridge="${BRG}",macaddr="${MAC}${VLAN}${MTU}" >/dev/null
qm set $VMID \
-net0 virtio,bridge=${LAN_BRG},macaddr=${LAN_MAC}${LAN_VLAN}${MTU} \
-net1 virtio,bridge=${BRG},macaddr=${MAC}${VLAN}${MTU} >/dev/null
msg_ok "Bridge interfaces added"
if [ "$START_VM" = "yes" ]; then
msg_info "Starting OpenWrt VM"
qm start "$VMID"
qm start $VMID
msg_ok "Started OpenWrt VM"
fi

View File

@@ -579,10 +579,10 @@ msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
msg_info "Retrieving the URL for the OPNsense Qcow2 Disk Image"
# Use latest stable FreeBSD amd64 qcow2 VM image (generic, not UFS/ZFS)
RELEASE_LIST="$(curl -s https://download.freebsd.org/releases/VM-IMAGES/ \
| grep -Eo '[0-9]+\.[0-9]+-RELEASE' \
| sort -Vr \
| uniq)"
RELEASE_LIST="$(curl -s https://download.freebsd.org/releases/VM-IMAGES/ |
grep -Eo '[0-9]+\.[0-9]+-RELEASE' |
sort -Vr |
uniq)"
URL=""
FREEBSD_VER=""
for ver in $RELEASE_LIST; do
@@ -668,7 +668,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
msg_info "Bridge interfaces are being added."
qm set $VMID \
@@ -686,7 +686,7 @@ if [ -n "$WAN_BRG" ]; then
qm set $VMID \
-net1 virtio,bridge=${WAN_BRG},macaddr=${WAN_MAC} &>/dev/null
msg_ok "WAN interface added"
sleep 5 # Brief pause after adding network interface
sleep 5 # Brief pause after adding network interface
fi
send_line_to_vm "sh ./opnsense-bootstrap.sh.in -y -f -r 25.7"
msg_ok "OPNsense VM is being installed, do not close the terminal, or the installation will fail."

View File

@@ -549,7 +549,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -450,7 +450,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -530,7 +530,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -532,7 +532,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -531,7 +531,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if [ -n "$DISK_SIZE" ]; then
msg_info "Resizing disk to $DISK_SIZE GB"
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null

View File

@@ -530,7 +530,7 @@ mkdir -p "$CACHE_DIR" "$(dirname "$FILE_IMG")"
download_and_validate_xz "$URL" "$CACHE_FILE"
qm create "$VMID" -machine q35 -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
qm create $VMID -machine q35 -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
-cores "$CORE_COUNT" -memory "$RAM_SIZE" -name "$HN" -tags community-script \
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
@@ -545,13 +545,13 @@ IMPORT_OUT="$("${IMPORT_CMD[@]}" "$VMID" "$FILE_IMG" "$STORAGE" --format raw 2>&
DISK_REF="$(printf '%s\n' "$IMPORT_OUT" | sed -n "s/.*imported disk '\([^']\+\)'.*/\1/p" | tr -d "\r\"'")"
[[ -z "$DISK_REF" ]] && DISK_REF="$(pvesm list "$STORAGE" | awk -v id="$VMID" '$5 ~ ("vm-"id"-disk-") {print $1":"$5}' | sort | tail -n1)"
qm set "$VMID" \
--efidisk0 "${STORAGE}:0,efitype=4m" \
--scsi0 "${DISK_REF},ssd=1,discard=on" \
qm set $VMID \
--efidisk0 ${STORAGE}:0,efitype=4m \
--scsi0 ${DISK_REF},ssd=1,discard=on \
--boot order=scsi0 \
--serial0 socket >/dev/null
qm set "$VMID" --agent enabled=1 >/dev/null
qm resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
qm set $VMID --agent enabled=1 >/dev/null
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
DESCRIPTION=$(
cat <<EOF
@@ -583,7 +583,7 @@ DESCRIPTION=$(
</div>
EOF
)
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
qm set $VMID -description "$DESCRIPTION" >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Image Cache" \
--yesno "Keep downloaded Umbrel OS image for future VMs?\n\nFile: $CACHE_FILE" 10 70; then