forked from forkanization/Proxmox-arm64
Compare commits
354 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 64d78b1ab4 | |||
| a1d51ea790 | |||
| 414ccb5d4c | |||
| 728cf1ce73 | |||
| fc4c76f78e | |||
| 3ff7d0b403 | |||
| 33e7fcf048 | |||
| 35eefd7680 | |||
| d8f7b01640 | |||
| 695835d19d | |||
| 0ce02f98d3 | |||
| 2d5484e233 | |||
| 930760840c | |||
| 9ef8058194 | |||
| 7452b47c9f | |||
| f4c9cc1156 | |||
| e7cca5c779 | |||
| 5bef4f7b2a | |||
| 32c2b49569 | |||
| 38d3f2c868 | |||
| 57b9cde44d | |||
| f26410759a | |||
| d22879b5e9 | |||
| 8cdb218e38 | |||
| 409936a9fc | |||
| eceb52a67a | |||
| 2d3cae43cb | |||
| b603da7778 | |||
| 902aee0c0b | |||
| 6881f07437 | |||
| 06742f7ef5 | |||
| 32cd74e49f | |||
| 28896707bc | |||
| 0340aec142 | |||
| 8a21f6e7f0 | |||
| 77b06ee3f9 | |||
| 399786c5bd | |||
| e4912cec78 | |||
| 846d75dca1 | |||
| af0376f25b | |||
| 5ae25108ef | |||
| 55c8d1187b | |||
| 9a5d43e4d3 | |||
| bb2c143cc8 | |||
| 2a844122d0 | |||
| 540fcd24f2 | |||
| c2c48b52c7 | |||
| 744e183eea | |||
| 468a5d367d | |||
| edf0753120 | |||
| 64eab60a4c | |||
| 5c711293b9 | |||
| 1d83562661 | |||
| 4626a17332 | |||
| 276ac07651 | |||
| d26994c597 | |||
| 875297b7d2 | |||
| f5978717d4 | |||
| 7176eaa99d | |||
| 2184eab0c5 | |||
| 88da093cf5 | |||
| 612979a040 | |||
| b4732cd8e9 | |||
| 0ab3151825 | |||
| 226697f810 | |||
| aadcb5b264 | |||
| e3ea08b788 | |||
| b097bd0c8b | |||
| 8dd3861a96 | |||
| c9f7f6447d | |||
| 34917b15f5 | |||
| d11ad56158 | |||
| 824710ddd4 | |||
| 8a4bb5d35d | |||
| 007c4cab49 | |||
| f9f4a53a74 | |||
| 8206f0b3dc | |||
| 30a5147fba | |||
| 09721e7cae | |||
| 50ce6fd6df | |||
| e9940cc535 | |||
| 087d635fd4 | |||
| f75fbc8d50 | |||
| 128b076731 | |||
| 95dbf93591 | |||
| 9a0cb6b8f5 | |||
| dbcb900da4 | |||
| cac29c8f5c | |||
| 1fb144306c | |||
| 5b22df5c8e | |||
| e2e4784136 | |||
| e995fb4f30 | |||
| dd3a32986a | |||
| 7d26b42163 | |||
| ec24441a2a | |||
| f3408ed4f3 | |||
| efd6d74edb | |||
| dbc4ce0231 | |||
| e643fe6699 | |||
| fe9736fd38 | |||
| 1ec52d08a3 | |||
| 32c24f69a7 | |||
| 3e2dc1cc1c | |||
| 7ae803092e | |||
| 6ead7e1e5f | |||
| e705fb6805 | |||
| 23b391b21d | |||
| e377e065a4 | |||
| 3237e6aced | |||
| 22e7ff1f17 | |||
| badff00ee2 | |||
| 0665e77a1c | |||
| 6e7b5d8022 | |||
| 11c5f518a0 | |||
| 0618c89147 | |||
| b7baf2d1ed | |||
| b323313d6e | |||
| e3160b56af | |||
| d442fa49f5 | |||
| 7e061a112f | |||
| 221ed9d260 | |||
| 8847505782 | |||
| 9703f8d88d | |||
| a9042ffdc1 | |||
| 301fc39a85 | |||
| af5a84fbe0 | |||
| 5dbb000070 | |||
| f3d8f9fa76 | |||
| 715868bda2 | |||
| d9789d1685 | |||
| 80f678a2b3 | |||
| f5d1d21ac6 | |||
| 8d8b152f6f | |||
| 79e0c29e33 | |||
| af5218d0a1 | |||
| 6fbb8ab4a2 | |||
| 36805ae6bb | |||
| 4c83a790ac | |||
| b7fe85cd5b | |||
| a10a0f09dd | |||
| e9ec4c4f8e | |||
| 741f38fe2f | |||
| eb881fefa6 | |||
| 6bee7e291e | |||
| 5420269e97 | |||
| 2554560082 | |||
| 6f98a65692 | |||
| 906e01b846 | |||
| 7e4d7597df | |||
| 79d77bb22d | |||
| 72b3876fee | |||
| 542a8a619b | |||
| 97d48dd4b7 | |||
| 6bb46a5365 | |||
| 05062bab40 | |||
| 71107fedc4 | |||
| 8335fbd3d5 | |||
| bb6759aae8 | |||
| 9aec831f92 | |||
| f2966ced7f | |||
| 6191d8e792 | |||
| f2937febe6 | |||
| f2fe361224 | |||
| 87a8d9c2d8 | |||
| 9a17e03a38 | |||
| 015e8f4393 | |||
| 16f5154705 | |||
| 1ff0979cee | |||
| 479a7104fa | |||
| a0686277f7 | |||
| 1a14c87209 | |||
| 499d564d29 | |||
| 4ead590cf4 | |||
| 5f34c2c7c8 | |||
| f2662027a8 | |||
| 0cea52ddb9 | |||
| 6a02ba1335 | |||
| e140642b1f | |||
| 61b0ca67cc | |||
| 649590eea7 | |||
| da30cd5c1e | |||
| ae7217048f | |||
| 1ea00c4775 | |||
| 72d3d64a48 | |||
| 085f1965a3 | |||
| 9543941d07 | |||
| 695793a151 | |||
| 93ed909fff | |||
| abe337e52d | |||
| 8ace224138 | |||
| 620b652864 | |||
| fa2e4786af | |||
| e4d342c819 | |||
| c567efe374 | |||
| 27bfa24cfe | |||
| a773864a1a | |||
| fe3b17b59d | |||
| 02468cc44d | |||
| 1fd5114183 | |||
| 80feaf6fa5 | |||
| b6890ccfbe | |||
| 3bd32110d9 | |||
| dc1adaba01 | |||
| b14a33ffac | |||
| 07df1c8373 | |||
| 0ee61aa092 | |||
| 389b03568d | |||
| d623c08825 | |||
| c502e413de | |||
| 30850b67f9 | |||
| 73eaf2e6a5 | |||
| 6d89c2de12 | |||
| 1e5f4b152e | |||
| 4cddfa3b12 | |||
| 4d9d7a8242 | |||
| b129cb1767 | |||
| b7295d7015 | |||
| 4b824b4d5f | |||
| eeb50db0e7 | |||
| 07895a7c23 | |||
| 103ac46a9f | |||
| 5fb1be4e41 | |||
| 86a5c8c1ba | |||
| c926ed1fbc | |||
| 890be3afbc | |||
| ef55baf25a | |||
| 2d6f2d0e94 | |||
| f23b3cea13 | |||
| 030d477cc3 | |||
| cb8318bf08 | |||
| e680dab28f | |||
| c9e271dac7 | |||
| 75c98d8e68 | |||
| 7f66b187fd | |||
| 6cb0bc59d9 | |||
| 96c8062405 | |||
| 4696040e93 | |||
| df3047e295 | |||
| 158c309d71 | |||
| 253da053fe | |||
| 3fc4aa4a6e | |||
| 9ad778ca52 | |||
| 9d76662d76 | |||
| fef858ed7b | |||
| 4844a00316 | |||
| d5e66a25ff | |||
| 2281a20b75 | |||
| 21abd09052 | |||
| 7d77be87d5 | |||
| cbde1b8419 | |||
| bb0a39e3c4 | |||
| 553e514ed8 | |||
| 561419f1a2 | |||
| 723365a79d | |||
| 9d579083bf | |||
| de1a4b0914 | |||
| aec826bbb3 | |||
| 9db6aa8fbb | |||
| bfa2b0c0ee | |||
| 52bfc1725f | |||
| 0a33d1739e | |||
| 28085bb2e7 | |||
| 631ef46466 | |||
| 604b7ee628 | |||
| 72dfc20090 | |||
| aca97a3da3 | |||
| e4ad002ce5 | |||
| 448cf93163 | |||
| 41b63495db | |||
| 08debd9442 | |||
| a28eb2fd46 | |||
| 3c41499074 | |||
| 858e58d7fd | |||
| 88de3536ab | |||
| d43e2ca4e1 | |||
| 23ebc32489 | |||
| 2782502e06 | |||
| 9c88dcdbd6 | |||
| e428bb8604 | |||
| daa896894d | |||
| 34fb023df4 | |||
| f95165b5ce | |||
| 43a3e0ef23 | |||
| 6d1cc92b59 | |||
| 92452db3e5 | |||
| d26e474ccb | |||
| b66590f976 | |||
| 4a1e02a9ab | |||
| ddb6551565 | |||
| 20fb0ce808 | |||
| c4b6ea33aa | |||
| a5fece4292 | |||
| 232919d6be | |||
| d21760cc65 | |||
| 341e873eba | |||
| d073535346 | |||
| b567bd848b | |||
| bfce73c0ed | |||
| 880a0f52ec | |||
| ea1cef7db5 | |||
| 026b0f4105 | |||
| b108b6e373 | |||
| fabbe5925b | |||
| 5e561a1b78 | |||
| a35e23916e | |||
| f59c1227be | |||
| 32ae8c1f4f | |||
| 2c58bc987c | |||
| 136f667126 | |||
| ae49faec93 | |||
| b73557c14f | |||
| 8db7e57819 | |||
| d18e37166d | |||
| 80fb3ee841 | |||
| 2af0be0e0f | |||
| 6c155c7463 | |||
| 2febf2c39b | |||
| cfa1b2e04d | |||
| 9deea7a983 | |||
| 00a8f07170 | |||
| 9cbd0f3037 | |||
| bf40c30fff | |||
| 466f994bb3 | |||
| e3da97472e | |||
| 2446b6599f | |||
| 19fef65ac0 | |||
| 8892fd960f | |||
| 7dbdd43781 | |||
| e46374a045 | |||
| 22c7801217 | |||
| 3a65f89cab | |||
| dea64a66cf | |||
| 0442f78b86 | |||
| 8ecee69f79 | |||
| 446e874dc1 | |||
| 0ee5ec3d84 | |||
| 186f186e8b | |||
| 9487fff510 | |||
| 8562dd1b93 | |||
| dad9da5e67 | |||
| 496b9bf92c | |||
| 6596850918 | |||
| fc5ea73e45 | |||
| f64e8ef47b | |||
| e6b86f3d47 | |||
| 7daad62fad | |||
| 15be0761ff | |||
| 5ef5f0086e | |||
| 85418addac | |||
| ef27851d31 | |||
| e53542834f | |||
| 5fcae037c2 | |||
| cd0df16a32 | |||
| eab4160c33 |
+136
-14
@@ -3,27 +3,149 @@
|
|||||||
<img src="https://raw.githubusercontent.com/tteck/Proxmox/main/misc/images/logo.png" height="100px" />
|
<img src="https://raw.githubusercontent.com/tteck/Proxmox/main/misc/images/logo.png" height="100px" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1 align="center">Change Log</h1>
|
<h1 align="center">Changelog</h1>
|
||||||
|
|
||||||
<h3 align="center">All notable changes to this project will be documented in this file.</h3>
|
<h3 align="center">All notable changes to this project will be documented in this file.</h3>
|
||||||
|
|
||||||
- All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
|
> [!CAUTION]
|
||||||
|
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
|
||||||
|
|
||||||
|
## 2024-10-27
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Open WebUI LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/8a21f6e7f025a911865395d4c0fa9a001bd0d512)
|
||||||
|
- Refactor Script to add an option to install Ollama.
|
||||||
|
|
||||||
|
## 2024-10-26
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **AdventureLog LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/adventurelog-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-10-25
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Zoraxy LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/468a5d367ded4cf453a1507452e112ac3e234e2a)
|
||||||
|
- Switch built from source to a pre-compiled binary version.
|
||||||
|
- Breaking Change
|
||||||
|
|
||||||
|
## 2024-10-23
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Wallos LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/wallos-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
- **Open WebUI LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/openwebui-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-10-19
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Cockpit LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/cockpit-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
- **Neo4j LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/neo4j-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-10-18
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **ArchiveBox LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/archivebox-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-10-15
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **evcc LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/evcc-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-10-10
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **MySQL LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/mysql-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
- **Tianji LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/4c83a790ac9b040da1f11ad2cbe13d3fc5f480e9)
|
||||||
|
- Breaking Change
|
||||||
|
- Switch from `pm2` process management to `systemd`
|
||||||
|
|
||||||
|
## 2024-10-03
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Home Assistant Core LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/f2937febe69b2bad8b3a14eb84aa562a8f14cc6a) [(Commit)](https://github.com/tteck/Proxmox/commit/f2966ced7f457fd506f865f7f5b70ea12c4b0049)
|
||||||
|
- Refactor Code
|
||||||
|
- Breaking Change
|
||||||
|
- Home Assistant has transitioned to using `uv` for managing the virtual environment and installing additional modules.
|
||||||
|
|
||||||
|
## 2024-09-16
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **HomeBox LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/homebox-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
- **Zipline LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/zipline-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-09-13
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Tianji LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/tianji-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-08-21
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **WireGuard LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/723365a79df7cc0fd29b1af8f7ef200a7e0921b1)
|
||||||
|
- Refactor Code
|
||||||
|
- Breaking Change
|
||||||
|
|
||||||
|
## 2024-08-19
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **CommaFeed LXC** [(Commit)](https://github.com/tteck/Proxmox/commit/0a33d1739ec3a49011411929bd46a260e92e99f9)
|
||||||
|
- Refactor Code
|
||||||
|
- Breaking Change
|
||||||
|
|
||||||
|
## 2024-08-06
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **lldap LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/lldap-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
|
## 2024-07-26
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Gitea LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/gitea-install.sh)
|
||||||
|
- NEW Script
|
||||||
|
|
||||||
## 2024-06-30
|
## 2024-06-30
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **All Scripts**
|
- **All Scripts** [(Commit)](https://github.com/tteck/Proxmox/commit/39ea1d4a20b83c07d084ebafdc811eec3548f289)
|
||||||
- Requires Proxmox Virtual Environment version 8.1 or later.
|
- Requires Proxmox Virtual Environment version 8.1 or later.
|
||||||
|
|
||||||
## 2024-06-27
|
## 2024-06-27
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Kubo LXC**
|
- **Kubo LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/kubo-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **RabbitMQ LXC**
|
- **RabbitMQ LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/rabbitmq-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **Scrutiny LXC**
|
- **Scrutiny LXC**
|
||||||
- Removed from website, broken.
|
- Removed from website, broken.
|
||||||
@@ -39,27 +161,27 @@
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **MySpeed LXC**
|
- **MySpeed LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/myspeed-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
|
|
||||||
## 2024-06-13
|
## 2024-06-13
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **PeaNUT LXC**
|
- **PeaNUT LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/peanut-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **Website**
|
- **Website**
|
||||||
- If the Changelog has changed recently, the link on the website will pulse.
|
- If the Changelog has changed recently, the link on the website will pulse.
|
||||||
- **Spoolman LXC**
|
- **Spoolman LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/spoolman-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
|
|
||||||
## 2024-06-12
|
## 2024-06-12
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **MeTube LXC**
|
- **MeTube LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/metube-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **Matterbridge LXC**
|
- **Matterbridge LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/matterbridge-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **Website**
|
- **Website**
|
||||||
- Reopen the gh-pages site (https://tteck.github.io/Proxmox/)
|
- Reopen the gh-pages site (https://tteck.github.io/Proxmox/)
|
||||||
@@ -68,14 +190,14 @@
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Zabbix LXC**
|
- **Zabbix LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/zabbix-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
|
|
||||||
## 2024-06-06
|
## 2024-06-06
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Petio LXC**
|
- **Petio LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/petio-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
- **Website**
|
- **Website**
|
||||||
- Important notices will now be displayed on the landing page.
|
- Important notices will now be displayed on the landing page.
|
||||||
@@ -84,14 +206,14 @@
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **FlareSolverr LXC**
|
- **FlareSolverr LXC** [(View Source)](https://github.com/tteck/Proxmox/blob/main/install/flaresolverr-install.sh)
|
||||||
- NEW Script
|
- NEW Script
|
||||||
|
|
||||||
## 2024-05-31
|
## 2024-05-31
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Advanced Settings**
|
- **Advanced Settings** [(Commit)](https://github.com/tteck/Proxmox/commit/fc9dff220b4ea426d3a75178ad8accacae4683ca)
|
||||||
- Passwords are now masked
|
- Passwords are now masked
|
||||||
|
|
||||||
## 2024-05-30
|
## 2024-05-30
|
||||||
|
|||||||
@@ -31,199 +31,6 @@ Any issues with the scripts, please put an issue within this repository rather t
|
|||||||
|
|
||||||
If you would like to offer support, I would appreciate a star on the repository, or for you to support the creator of the Proxmox scripts [tteck on Ko-Fi](https://ko-fi.com/D1D7EP4GF)!
|
If you would like to offer support, I would appreciate a star on the repository, or for you to support the creator of the Proxmox scripts [tteck on Ko-Fi](https://ko-fi.com/D1D7EP4GF)!
|
||||||
|
|
||||||
## VM Compatibility Guide
|
## Compatibility Guide
|
||||||
|
|
||||||
| Icon | Description |
|
[View Compatibility Guide here](https://pimox-scripts.com)
|
||||||
| ---- | -------------------------------------------------- |
|
|
||||||
| ☑️ | Creating the LXC using the script has been tested. |
|
|
||||||
| ⭕ | Install script is ported, but has not been tested. |
|
|
||||||
| ❌ | Unsupported. View notes for reason. |
|
|
||||||
| 🔘 | Install script not ported to ARM64. |
|
|
||||||
|
|
||||||
| OS | Status | Notes |
|
|
||||||
| ------------------------------- | ------ | -------------------------------------------------------------------------------------------------------- |
|
|
||||||
| Debian | ⭕ | Needs testing. |
|
|
||||||
| Home Assistant OS | ❌ | Use Pimox HAOS VM script. |
|
|
||||||
| Mikrotik RouterOS | ❌ | No arm64 image available. |
|
|
||||||
| NextCloud | ❌ | No arm64 image available. Not present on website. |
|
|
||||||
| OpenWRT | ⭕ | Needs testing. |
|
|
||||||
| OwnCloud | ❌ | No arm64 image available. |
|
|
||||||
| Pimox HAOS | ☑️ | |
|
|
||||||
| Ubuntu 22.04 | ⭕ | Needs testing. |
|
|
||||||
| Ubuntu 24.04 | ⭕ | Needs testing. |
|
|
||||||
|
|
||||||
## LXC Compatibility Guide
|
|
||||||
|
|
||||||
| App | Status | Notes |
|
|
||||||
| ------------------------------- | ------ | -------------------------------------------------------------------------------------------------------- |
|
|
||||||
| Actual Budget | ☑️ | |
|
|
||||||
| AdGuard Home | ☑️ | |
|
|
||||||
| AgentDVR | ☑️ | |
|
|
||||||
| Apache-Cassandra | ☑️ | |
|
|
||||||
| Alpine Docker | ☑️ | |
|
|
||||||
| Alpine Grafana | ☑️ | |
|
|
||||||
| Alpine | ☑️ | |
|
|
||||||
| Alpine Nextcloud | ☑️ | |
|
|
||||||
| Alpine Vaultwarden | ☑️ | |
|
|
||||||
| Alpine Zigbee2mqtt | ☑️ | |
|
|
||||||
| Apache-CouchDB | ☑️ | |
|
|
||||||
| Apt-Cacher-NG | ☑️ | Won't work with Debian template from before 2024/06/08 (need to delete tar /var/lib/vz/template/cache/). |
|
|
||||||
| Aria2 | ☑️ | |
|
|
||||||
| Audiobookshelf | ☑️ | |
|
|
||||||
| Autobrr | ☑️ | |
|
|
||||||
| Bazarr | ☑️ | |
|
|
||||||
| Blocky | ☑️ | |
|
|
||||||
| Caddy | ☑️ | |
|
|
||||||
| Calibre-Web | ☑️ | |
|
|
||||||
| CasaOS | ☑️ | |
|
|
||||||
| Change Detection | ☑️ | |
|
|
||||||
| Channels DVR Server | ☑️ | |
|
|
||||||
| Cloudflared | ☑️ | |
|
|
||||||
| CommaFeed | ☑️ | |
|
|
||||||
| Cronicle Primary | ☑️ | |
|
|
||||||
| Dashy | ☑️ | |
|
|
||||||
| deCONZ | ☑️ | |
|
|
||||||
| Daemon Sync Server | ❌ | Built for x64 only. |
|
|
||||||
| Debian | ☑️ | |
|
|
||||||
| Deluge | ☑️ | |
|
|
||||||
| Docker | ☑️ | |
|
|
||||||
| Dockge | ☑️ | |
|
|
||||||
| Emby Media Server | ☑️ | |
|
|
||||||
| EMQX | ☑️ | |
|
|
||||||
| ErsatzTV | ☑️ | |
|
|
||||||
| ESPHome | ☑️ | |
|
|
||||||
| Fenrus | ☑️ | |
|
|
||||||
| FHEM | ☑️ | |
|
|
||||||
| FlareSolverr | ☑️ | |
|
|
||||||
| FlowiseAI | ☑️ | |
|
|
||||||
| Forgejo | ☑️ | |
|
|
||||||
| Frigate | ☑️ | |
|
|
||||||
| go2rtc | ☑️ | |
|
|
||||||
| Gokapi | ☑️ | |
|
|
||||||
| Gotify | ☑️ | |
|
|
||||||
| Grafana | ☑️ | |
|
|
||||||
| grocy | ☑️ | |
|
|
||||||
| Heimdall Dashboard | ☑️ | |
|
|
||||||
| HiveMQ CE | ☑️ | |
|
|
||||||
| Homarr | ☑️ | |
|
|
||||||
| Home Assistant Core | ☑️ | |
|
|
||||||
| Home Assistant Container | ☑️ | |
|
|
||||||
| Homebridge | ☑️ | |
|
|
||||||
| Homepage | ☑️ | |
|
|
||||||
| Homer | ☑️ | |
|
|
||||||
| HyperHDR | ☑️ | |
|
|
||||||
| Hyperion | ☑️ | |
|
|
||||||
| InfluxDB | ☑️ | |
|
|
||||||
| ioBroker | ☑️ | |
|
|
||||||
| iVentoy | ☑️ | |
|
|
||||||
| Jackett | ☑️ | |
|
|
||||||
| Jellyfin Media Server | ☑️ | |
|
|
||||||
| Jellyseerr | ☑️ | |
|
|
||||||
| k0s | ☑️ | |
|
|
||||||
| Kavita | ☑️ | |
|
|
||||||
| Keycloak | ☑️ | |
|
|
||||||
| Kubo | ☑️ | |
|
|
||||||
| LazyLibrarian | ☑️ | |
|
|
||||||
| Lidarr | ☑️ | |
|
|
||||||
| Linkwarden | ☑️ | |
|
|
||||||
| Mafl | ☑️ | |
|
|
||||||
| MagicMirror Server | ☑️ | |
|
|
||||||
| Mariadb | ☑️ | |
|
|
||||||
| Matterbridge | ☑️ | |
|
|
||||||
| MediaMTX | ☑️ | |
|
|
||||||
| Medusa | ☑️ | |
|
|
||||||
| MeshCentral | ☑️ | |
|
|
||||||
| MeTube | ☑️ | |
|
|
||||||
| MongoDB | ☑️ | Only supports ARMv8.2-a currently. (no RPI4 support). |
|
|
||||||
| MotionEye NVR | ☑️ | |
|
|
||||||
| MQTT | ☑️ | |
|
|
||||||
| n8n | ☑️ | |
|
|
||||||
| MySpeed | ☑️ | |
|
|
||||||
| Navidrome | ☑️ | |
|
|
||||||
| NextCloudPi | ☑️ | |
|
|
||||||
| Nginx Proxy Manager | ☑️ | |
|
|
||||||
| NocoDB | ☑️ | |
|
|
||||||
| Node-Red | ☑️ | |
|
|
||||||
| Notifiarr | ☑️ | |
|
|
||||||
| ntfy | ☑️ | |
|
|
||||||
| OctoPrint | ☑️ | |
|
|
||||||
| Omada Controller | ☑️ | |
|
|
||||||
| Ombi | ☑️ | |
|
|
||||||
| OpenMediaVault | ☑️ | |
|
|
||||||
| openHAB | ☑️ | |
|
|
||||||
| OpenObserve | ☑️ | |
|
|
||||||
| Overseerr | ☑️ | |
|
|
||||||
| Owncast | ☑️ | |
|
|
||||||
| PairDrop | ☑️ | |
|
|
||||||
| Paperless-ngx | ☑️ | |
|
|
||||||
| PBS | ☑️ | Proxmox Backup Server |
|
|
||||||
| PeaNUT | ☑️ | |
|
|
||||||
| Petio | ☑️ | Only supports ARMv8.2-a currently. (no RPI4 support). |
|
|
||||||
| PhotoPrism | ☑️ | |
|
|
||||||
| Pi.Alert | ☑️ | |
|
|
||||||
| Pi-Hole | ☑️ | |
|
|
||||||
| Pingvin Share | ☑️ | |
|
|
||||||
| Plex Media Server | ☑️ | |
|
|
||||||
| Pocketbase | ☑️ | |
|
|
||||||
| Podman Home Assistant Container | ☑️ | |
|
|
||||||
| Podman | ☑️ | |
|
|
||||||
| PostgreSQL | ☑️ | |
|
|
||||||
| Prometheus | ☑️ | |
|
|
||||||
| Prowlarr | ☑️ | |
|
|
||||||
| qBittorrent | ☑️ | |
|
|
||||||
| RabbitMQ | ☑️ | |
|
|
||||||
| Radarr | ☑️ | |
|
|
||||||
| RDTClient | ☑️ | Real-Debrid Torrent Client |
|
|
||||||
| Readarr | ☑️ | |
|
|
||||||
| Readeck | ☑️ | |
|
|
||||||
| Redis | ☑️ | |
|
|
||||||
| RTSPtoWeb | ☑️ | |
|
|
||||||
| Runtipi | ☑️ | |
|
|
||||||
| SABnzbd | ☑️ | |
|
|
||||||
| Scrypted | ☑️ | |
|
|
||||||
| Scrutiny | ☑️ | |
|
|
||||||
| SFTPGo | ☑️ | |
|
|
||||||
| Shinobi NVR | ☑️ | |
|
|
||||||
| SmokePing | ☑️ | |
|
|
||||||
| Sonarr | ☑️ | |
|
|
||||||
| SpoolMan | ☑️ | |
|
|
||||||
| Stirling-PDF | ☑️ | |
|
|
||||||
| Syncthing | ☑️ | |
|
|
||||||
| Tandoor Recipes | ☑️ | |
|
|
||||||
| TasmoAdmin | ☑️ | |
|
|
||||||
| Tautulli | ☑️ | |
|
|
||||||
| Tdarr | ☑️ | |
|
|
||||||
| Technitium DNS | ☑️ | |
|
|
||||||
| Threadfin | ☑️ | |
|
|
||||||
| Traccar | ☑️ | |
|
|
||||||
| Traefik | ☑️ | |
|
|
||||||
| Transmission | ☑️ | |
|
|
||||||
| Trilium | ❌ | Built for x64 only. |
|
|
||||||
| Umami | ☑️ | |
|
|
||||||
| Ubuntu | ☑️ | |
|
|
||||||
| Umbrel | ☑️ | |
|
|
||||||
| UniFi Network Server | ☑️ | |
|
|
||||||
| Unmanic | ☑️ | |
|
|
||||||
| Uptime Kuma | ☑️ | |
|
|
||||||
| Vaultwarden | ☑️ | Will probably work on default install if you have a lot of ram. Otherwise use the Alpine Linux version. |
|
|
||||||
| Wastebin | ☑️ | |
|
|
||||||
| WatchYourLAN | ☑️ | |
|
|
||||||
| Whisparr | ☑️ | |
|
|
||||||
| Whoogle | ☑️ | |
|
|
||||||
| Wiki.js | ☑️ | |
|
|
||||||
| WireGuard | ☑️ | |
|
|
||||||
| YunoHost | ☑️ | |
|
|
||||||
| Zabbix | ☑️ | |
|
|
||||||
| Zigbee2MQTT | ☑️ | |
|
|
||||||
| Zoraxy | ☑️ | |
|
|
||||||
| Z-Wave JS UI | ☑️ | |
|
|
||||||
|
|
||||||
## Miscellaneous Compatibility Guide
|
|
||||||
|
|
||||||
| Script | Status | Notes |
|
|
||||||
| -------------- | ------ | -------------------- |
|
|
||||||
| File Browser | ☑️ | |
|
|
||||||
| OliveTin | ☑️ | |
|
|
||||||
| NetBird | ☑️ | No changes required. |
|
|
||||||
| Tailscale | ☑️ | No changes required. |
|
|
||||||
| VS Code Server | ☑️ | |
|
|
||||||
@@ -38,3 +38,7 @@
|
|||||||
[Proxmox + NetData](<https://dbt3ch.com/books/proxmox-netdata-for-better-insights-and-notifications/page/proxmox-netdata-for-better-insights-and-notifications>)
|
[Proxmox + NetData](<https://dbt3ch.com/books/proxmox-netdata-for-better-insights-and-notifications/page/proxmox-netdata-for-better-insights-and-notifications>)
|
||||||
|
|
||||||
[Proxmox Homelab Series](<https://blog.kye.dev/proxmox-series>)
|
[Proxmox Homelab Series](<https://blog.kye.dev/proxmox-series>)
|
||||||
|
|
||||||
|
[The fastest installation of Docker and Portainer on Proxmox VE](https://lavr.site/en-fastest-install-docker-portainer-proxmox/)
|
||||||
|
|
||||||
|
[How To Setup Proxmox Backuper Server Using Helper Scripts](<https://youtu.be/6C2JOsrZZZw?si=kkrrcL_nLCDBJkOB>)
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
___ __ __ __
|
||||||
|
/ | ____/ / _____ ____ / /___ __________ / / ____ ____ _
|
||||||
|
/ /| |/ __ / | / / _ \/ __ \/ __/ / / / ___/ _ \/ / / __ \/ __ `/
|
||||||
|
/ ___ / /_/ /| |/ / __/ / / / /_/ /_/ / / / __/ /___/ /_/ / /_/ /
|
||||||
|
/_/ |_\__,_/ |___/\___/_/ /_/\__/\__,_/_/ \___/_____/\____/\__, /
|
||||||
|
/____/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="AdventureLog"
|
||||||
|
var_disk="7"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="2048"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/adventurelog ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/seanmorley15/AdventureLog/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop adventurelog-backend
|
||||||
|
systemctl stop adventurelog-frontend
|
||||||
|
msg_ok "Services Stopped"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cp /opt/adventurelog/backend/server/.env /opt/server.env
|
||||||
|
cp /opt/adventurelog/frontend/env /opt/frontend.env
|
||||||
|
wget -q "https://github.com/seanmorley15/AdventureLog/archive/refs/tags/v${RELEASE}.zip"
|
||||||
|
unzip -q v${RELEASE}.zip
|
||||||
|
mv AdventureLog-${RELEASE} /opt/adventurelog
|
||||||
|
mv /opt/server.env /opt/adventurelog/backend/server/.env
|
||||||
|
cd /opt/adventurelog/backend/server
|
||||||
|
pip install --upgrade pip &>/dev/null
|
||||||
|
pip install -r requirements.txt &>/dev/null
|
||||||
|
python3 manage.py collectstatic --noinput &>/dev/null
|
||||||
|
python3 manage.py migrate &>/dev/null
|
||||||
|
|
||||||
|
mv /opt/frontend.env /opt/adventurelog/frontend/.env
|
||||||
|
cd /opt/adventurelog/frontend
|
||||||
|
pnpm install &>/dev/null
|
||||||
|
pnpm run build &>/dev/null
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
systemctl start adventurelog-backend
|
||||||
|
systemctl start adventurelog-frontend
|
||||||
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf v${RELEASE}.zip
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:3000${CL} \n"
|
||||||
@@ -71,7 +71,7 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
case $CHOICE in
|
case $CHOICE in
|
||||||
1)
|
1)
|
||||||
apk update && apk upgrade
|
apk update && apk upgrade && rc-service vaultwarden restart -q
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
___ __ _ ____
|
||||||
|
/ | __________/ /_ (_) _____ / __ )____ _ __
|
||||||
|
/ /| | / ___/ ___/ __ \/ / | / / _ \/ __ / __ \| |/_/
|
||||||
|
/ ___ |/ / / /__/ / / / /| |/ / __/ /_/ / /_/ /> <
|
||||||
|
/_/ |_/_/ \___/_/ /_/_/ |___/\___/_____/\____/_/|_|
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="ArchiveBox"
|
||||||
|
var_disk="8"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/archivebox ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop archivebox
|
||||||
|
msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP}"
|
||||||
|
cd /opt/archivebox/data
|
||||||
|
pip install --upgrade --ignore-installed archivebox
|
||||||
|
sudo -u archivebox archivebox init
|
||||||
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start archivebox
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:8000/admin/login${CL} \n"
|
||||||
+20
-5
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
# Copyright (c) 2021-2024 tteck
|
# Copyright (c) 2021-2024 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT
|
# License: MIT
|
||||||
@@ -55,10 +55,25 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /etc/bunkerweb ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /etc/bunkerweb ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating $APP"
|
|
||||||
apt-get update &>/dev/null
|
RELEASE=$(curl -s https://api.github.com/repos/bunkerity/bunkerweb/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
apt-get -y upgrade &>/dev/null
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
msg_ok "Updated $APP"
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cat <<EOF >/etc/apt/preferences.d/bunkerweb
|
||||||
|
Package: bunkerweb
|
||||||
|
Pin: version ${RELEASE}
|
||||||
|
Pin-Priority: 1001
|
||||||
|
EOF
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y nginx=1.26.2*
|
||||||
|
apt-get install -y bunkerweb=${RELEASE}
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -65,8 +65,6 @@ function update_script() {
|
|||||||
rm kepubify-linux-arm64
|
rm kepubify-linux-arm64
|
||||||
curl -fsSLO https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-arm64 &>/dev/null
|
curl -fsSLO https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-arm64 &>/dev/null
|
||||||
chmod +x kepubify-linux-arm64
|
chmod +x kepubify-linux-arm64
|
||||||
rm /opt/calibre-web/metadata.db
|
|
||||||
wget https://github.com/janeczku/calibre-web/raw/master/library/metadata.db -P /opt/calibre-web
|
|
||||||
menu_array=("1" "Enables gdrive as storage backend for your ebooks" OFF \
|
menu_array=("1" "Enables gdrive as storage backend for your ebooks" OFF \
|
||||||
"2" "Enables sending emails via a googlemail account without enabling insecure apps" OFF \
|
"2" "Enables sending emails via a googlemail account without enabling insecure apps" OFF \
|
||||||
"3" "Enables displaying of additional author infos on the authors page" OFF \
|
"3" "Enables displaying of additional author infos on the authors page" OFF \
|
||||||
@@ -83,7 +81,7 @@ function update_script() {
|
|||||||
line=0
|
line=0
|
||||||
elif [ $i == "gmail" ]; then
|
elif [ $i == "gmail" ]; then
|
||||||
line=1
|
line=1
|
||||||
elif [ $i == "goodreads" ]; then
|
elif [ $i == "goodreads" ]; then
|
||||||
line=2
|
line=2
|
||||||
elif [ $i == "ldap" ]; then
|
elif [ $i == "ldap" ]; then
|
||||||
line=3
|
line=3
|
||||||
@@ -104,8 +102,8 @@ function update_script() {
|
|||||||
CHOICES=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CALIBRE-WEB OPTIONS" --separate-output --checklist "Choose Additional Options" 15 125 8 "${menu_array[@]}" 3>&1 1>&2 2>&3)
|
CHOICES=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CALIBRE-WEB OPTIONS" --separate-output --checklist "Choose Additional Options" 15 125 8 "${menu_array[@]}" 3>&1 1>&2 2>&3)
|
||||||
spinner &
|
spinner &
|
||||||
SPINNER_PID=$!
|
SPINNER_PID=$!
|
||||||
|
options=()
|
||||||
if [ ! -z "$CHOICES" ]; then
|
if [ ! -z "$CHOICES" ]; then
|
||||||
declare -a options
|
|
||||||
for CHOICE in $CHOICES; do
|
for CHOICE in $CHOICES; do
|
||||||
case "$CHOICE" in
|
case "$CHOICE" in
|
||||||
"1")
|
"1")
|
||||||
|
|||||||
@@ -62,6 +62,17 @@ if ! dpkg -s libjpeg-dev >/dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
pip3 install changedetection.io --upgrade &>/dev/null
|
pip3 install changedetection.io --upgrade &>/dev/null
|
||||||
pip3 install playwright --upgrade &>/dev/null
|
pip3 install playwright --upgrade &>/dev/null
|
||||||
|
if [[ -f /etc/systemd/system/browserless.service ]]; then
|
||||||
|
git -C /opt/browserless/ fetch --all &>/dev/null
|
||||||
|
git -C /opt/browserless/ reset --hard origin/main &>/dev/null
|
||||||
|
npm update --prefix /opt/browserless &>/dev/null
|
||||||
|
npm run build --prefix /opt/browserless &>/dev/null
|
||||||
|
npm run build:function --prefix /opt/browserless &>/dev/null
|
||||||
|
npm prune production --prefix /opt/browserless &>/dev/null
|
||||||
|
systemctl restart browserless
|
||||||
|
else
|
||||||
|
msg_error "No Browserless Installation Found!"
|
||||||
|
fi
|
||||||
systemctl restart changedetection
|
systemctl restart changedetection
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
exit
|
exit
|
||||||
|
|||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: havardthom
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
______ __ _ __
|
||||||
|
/ ____/___ _____/ /______ (_) /_
|
||||||
|
/ / / __ \/ ___/ //_/ __ \/ / __/
|
||||||
|
/ /___/ /_/ / /__/ ,< / /_/ / / /_
|
||||||
|
\____/\____/\___/_/|_/ .___/_/\__/
|
||||||
|
/_/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Cockpit"
|
||||||
|
var_disk="4"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
if [[ ! -d /etc/cockpit ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 4 \
|
||||||
|
"1" "Update LXC" ON \
|
||||||
|
"2" "Install cockpit-file-sharing" OFF \
|
||||||
|
"3" "Install cockpit-identities" OFF \
|
||||||
|
"4" "Install cockpit-navigator" OFF \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
|
header_info
|
||||||
|
if [ "$UPD" == "1" ]; then
|
||||||
|
msg_info "Updating ${APP} LXC"
|
||||||
|
apt-get update &>/dev/null
|
||||||
|
apt-get -y upgrade &>/dev/null
|
||||||
|
msg_ok "Updated ${APP} LXC"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ "$UPD" == "2" ]; then
|
||||||
|
msg_info "Installing dependencies (patience)"
|
||||||
|
apt-get install -y attr &>/dev/null
|
||||||
|
apt-get install -y nfs-kernel-server &>/dev/null
|
||||||
|
apt-get install -y samba &>/dev/null
|
||||||
|
apt-get install -y samba-common-bin &>/dev/null
|
||||||
|
apt-get install -y winbind &>/dev/null
|
||||||
|
apt-get install -y gawk &>/dev/null
|
||||||
|
msg_ok "Installed dependencies"
|
||||||
|
msg_info "Installing Cockpit file sharing"
|
||||||
|
LATEST=$(curl -s https://api.github.com/repos/45Drives/cockpit-file-sharing/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
wget -q https://github.com/45Drives/cockpit-file-sharing/releases/download/v${LATEST}/cockpit-file-sharing_${LATEST}-1focal_all.deb
|
||||||
|
dpkg -i cockpit-file-sharing_${LATEST}-1focal_all.deb &>/dev/null
|
||||||
|
rm cockpit-file-sharing_${LATEST}-1focal_all.deb
|
||||||
|
msg_ok "Installed Cockpit file sharing"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ "$UPD" == "3" ]; then
|
||||||
|
msg_info "Installing dependencies (patience)"
|
||||||
|
apt-get install -y psmisc &>/dev/null
|
||||||
|
apt-get install -y samba &>/dev/null
|
||||||
|
apt-get install -y samba-common-bin &>/dev/null
|
||||||
|
msg_ok "Installed dependencies"
|
||||||
|
msg_info "Installing Cockpit identities"
|
||||||
|
LATEST=$(curl -s https://api.github.com/repos/45Drives/cockpit-identities/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
wget -q https://github.com/45Drives/cockpit-identities/releases/download/v${LATEST}/cockpit-identities_${LATEST}-1focal_all.deb
|
||||||
|
dpkg -i cockpit-identities_${LATEST}-1focal_all.deb &>/dev/null
|
||||||
|
rm cockpit-identities_${LATEST}-1focal_all.deb
|
||||||
|
msg_ok "Installed Cockpit identities"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ "$UPD" == "4" ]; then
|
||||||
|
msg_info "Installing dependencies"
|
||||||
|
apt-get install -y rsync &>/dev/null
|
||||||
|
apt-get install -y zip &>/dev/null
|
||||||
|
msg_ok "Installed dependencies"
|
||||||
|
msg_info "Installing Cockpit navigator"
|
||||||
|
LATEST=$(curl -s https://api.github.com/repos/45Drives/cockpit-navigator/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
wget -q https://github.com/45Drives/cockpit-navigator/releases/download/v${LATEST}/cockpit-navigator_${LATEST}-1focal_all.deb
|
||||||
|
dpkg -i cockpit-navigator_${LATEST}-1focal_all.deb &>/dev/null
|
||||||
|
rm cockpit-navigator_${LATEST}-1focal_all.deb
|
||||||
|
msg_ok "Installed Cockpit navigator"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:9090${CL} \n"
|
||||||
+19
-11
@@ -55,19 +55,27 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/commafeed ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/commafeed ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Stopping CommaFeed"
|
RELEASE=$(curl -sL https://api.github.com/repos/Athou/commafeed/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
|
||||||
systemctl stop commafeed
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
msg_ok "Stopped CommaFeed"
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop commafeed
|
||||||
|
msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
msg_info "Updating CommaFeed"
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
cd /opt/commafeed
|
wget -q https://github.com/Athou/commafeed/releases/download/${RELEASE}/commafeed-${RELEASE}-h2-jvm.zip
|
||||||
rm commafeed.jar
|
unzip -q commafeed-${RELEASE}-h2-jvm.zip
|
||||||
wget -q https://github.com/Athou/commafeed/releases/latest/download/commafeed.jar
|
rsync -a --exclude 'data/' commafeed-${RELEASE}-h2/ /opt/commafeed/
|
||||||
msg_ok "Updated CommaFeed"
|
rm -rf commafeed-${RELEASE}-h2 commafeed-${RELEASE}-h2-jvm.zip
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting CommaFeed"
|
msg_info "Starting ${APP}"
|
||||||
systemctl start commafeed
|
systemctl start commafeed
|
||||||
msg_ok "Update Completed Successfully"
|
msg_ok "Started ${APP}"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -76,8 +76,8 @@ if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}
|
|||||||
mkdir -p /opt/dashy
|
mkdir -p /opt/dashy
|
||||||
wget -qO- https://github.com/Lissy93/dashy/archive/refs/tags/${RELEASE}.tar.gz | tar -xz -C /opt/dashy --strip-components=1
|
wget -qO- https://github.com/Lissy93/dashy/archive/refs/tags/${RELEASE}.tar.gz | tar -xz -C /opt/dashy --strip-components=1
|
||||||
cd /opt/dashy
|
cd /opt/dashy
|
||||||
npm install &>/dev/null
|
npm install
|
||||||
npm run build &>/dev/null
|
npm run build
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to ${RELEASE}"
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
|
|||||||
+7
-9
@@ -32,7 +32,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
@@ -57,22 +57,20 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/ErsatzTV ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/ErsatzTV ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
|
||||||
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
|
||||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
|
||||||
fi
|
|
||||||
msg_info "Stopping ErsatzTV"
|
msg_info "Stopping ErsatzTV"
|
||||||
systemctl stop ersatzTV
|
systemctl stop ersatzTV
|
||||||
msg_ok "Stopped ErsatzTV"
|
msg_ok "Stopped ErsatzTV"
|
||||||
|
|
||||||
msg_info "Updating ErsatzTV"
|
msg_info "Updating ErsatzTV"
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/ErsatzTV/ErsatzTV/releases | grep -oP '"tag_name": "\K[^"]+' | head -n 1)
|
RELEASE=$(curl -s https://api.github.com/repos/ErsatzTV/ErsatzTV/releases | grep -oP '"tag_name": "\K[^"]+' | head -n 1)
|
||||||
if [ -d /opt/ErsatzTV/ErsatzTV_bak ]; then
|
cp -R /opt/ErsatzTV/ ErsatzTV-backup
|
||||||
rm -rf /opt/ErsatzTV/ErsatzTV_bak
|
rm ErsatzTV-backup/ErsatzTV
|
||||||
fi
|
rm -rf /opt/ErsatzTV
|
||||||
mv /opt/ErsatzTV/ErsatzTV /opt/ErsatzTV/ErsatzTV_bak
|
|
||||||
wget -qO- "https://github.com/ErsatzTV/ErsatzTV/releases/download/${RELEASE}/ErsatzTV-${RELEASE}-linux-arm64.tar.gz" | tar -xz -C /opt
|
wget -qO- "https://github.com/ErsatzTV/ErsatzTV/releases/download/${RELEASE}/ErsatzTV-${RELEASE}-linux-arm64.tar.gz" | tar -xz -C /opt
|
||||||
mv "/opt/ErsatzTV-${RELEASE}-linux-arm64" /opt/ErsatzTV
|
mv "/opt/ErsatzTV-${RELEASE}-linux-arm64" /opt/ErsatzTV
|
||||||
|
cp -R ErsatzTV-backup/* /opt/ErsatzTV/
|
||||||
|
rm -rf ErsatzTV-backup
|
||||||
msg_ok "Updated ErsatzTV"
|
msg_ok "Updated ErsatzTV"
|
||||||
|
|
||||||
msg_info "Starting ErsatzTV"
|
msg_info "Starting ErsatzTV"
|
||||||
|
|||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
___ _ ____________
|
||||||
|
/ _ \ | / / ___/ ___/
|
||||||
|
/ __/ |/ / /__/ /__
|
||||||
|
\___/|___/\___/\___/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="evcc"
|
||||||
|
var_disk="4"
|
||||||
|
var_cpu="1"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -f /etc/apt/sources.list.d/evcc-stable.list ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_info "Updating evcc LXC"
|
||||||
|
apt update &>/dev/null
|
||||||
|
apt --only-upgrade install -y evcc &>/dev/null
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:7070${CL} \n"
|
||||||
@@ -56,6 +56,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/flaresolverr.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/flaresolverr.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
RELEASE=$(wget -q https://github.com/FlareSolverr/FlareSolverr/releases/latest -O - | grep "title>Release" | cut -d " " -f 4)
|
RELEASE=$(wget -q https://github.com/FlareSolverr/FlareSolverr/releases/latest -O - | grep "title>Release" | cut -d " " -f 4)
|
||||||
if [[ ! -d /opt/flaresolverr ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/flaresolverr ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating $APP LXC"
|
msg_info "Updating $APP LXC"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/flowise.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/flowise.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
msg_info "Updating ${APP}"
|
msg_info "Updating ${APP}"
|
||||||
systemctl stop flowise
|
systemctl stop flowise
|
||||||
npm install -g flowise --upgrade
|
npm install -g flowise --upgrade
|
||||||
|
|||||||
+8
-3
@@ -55,7 +55,7 @@ function default_settings() {
|
|||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
if [[ ! -f /etc/systemd/system/frigate.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/frigate.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_error "There is currently no update path available."
|
msg_error "To update Frigate, create a new container and transfer your configuration."
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,13 @@ build_container
|
|||||||
description
|
description
|
||||||
|
|
||||||
msg_info "Setting Container to Normal Resources"
|
msg_info "Setting Container to Normal Resources"
|
||||||
pct set $CTID -memory 1024
|
STATUS=$(pct status $CTID | grep -oP '(?<=status: ).*')
|
||||||
msg_ok "Set Container to Normal Resources"
|
if [ "$STATUS" == "running" ]; then
|
||||||
|
pct set $CTID -memory 1024
|
||||||
|
else
|
||||||
|
echo -e " ⚠️ ${RD}Container is not running. Will need to change memory to 1024MB manually.${CL}"
|
||||||
|
fi
|
||||||
|
msg_ok "Set Normal Resources"
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${APP} should be reachable by going to the following URL.
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
${BL}http://${IP}:5000${CL} \n"
|
${BL}http://${IP}:5000${CL} \n"
|
||||||
|
|||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# Co-author: Rogue-King
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
______ _ __
|
||||||
|
/ ____/(_)/ /____ ____ _
|
||||||
|
/ / __// // __/ _ \/ __ /
|
||||||
|
/ /_/ // // /_/ __/ /_/ /
|
||||||
|
\____//_/ \__/\___/\__,_/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Gitea"
|
||||||
|
var_disk="8"
|
||||||
|
var_cpu="1"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -f /usr/local/bin/gitea ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
RELEASE=$(wget -q https://github.com/go-gitea/gitea/releases/latest -O - | grep "title>Release" | cut -d " " -f 4 | sed 's/^v//')
|
||||||
|
msg_info "Updating $APP to ${RELEASE}"
|
||||||
|
wget -q https://github.com/go-gitea/gitea/releases/download/v$RELEASE/gitea-$RELEASE-linux-arm64
|
||||||
|
systemctl stop gitea
|
||||||
|
rm -rf /usr/local/bin/gitea
|
||||||
|
mv gitea* /usr/local/bin/gitea
|
||||||
|
chmod +x /usr/local/bin/gitea
|
||||||
|
systemctl start gitea
|
||||||
|
msg_ok "Updated $APP Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:3000${CL} \n"
|
||||||
+23
-1
@@ -55,7 +55,29 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/gotify ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/gotify ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_error "There is currently no update path available."
|
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/gotify/server/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop gotify
|
||||||
|
msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cd /opt/gotify
|
||||||
|
wget -q https://github.com/gotify/server/releases/download/v${RELEASE}/gotify-linux-amd64.zip
|
||||||
|
unzip -oq gotify-linux-amd64.zip
|
||||||
|
rm -rf gotify-linux-amd64.zip
|
||||||
|
chmod +x gotify-linux-amd64
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start gotify
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
# Copyright (c) 2021-2024 tteck
|
# Copyright (c) 2021-2024 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck (tteckster)
|
||||||
# License: MIT
|
# License: MIT
|
||||||
@@ -63,9 +63,9 @@ if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}
|
|||||||
msg_ok "Stopped ${APP}"
|
msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
msg_info "Updating $APP to v${RELEASE}"
|
msg_info "Updating $APP to v${RELEASE}"
|
||||||
wget -q https://github.com/juanfont/headscale/releases/download/v${RELEASE}/headscale_${RELEASE}_linux_amd64.deb
|
wget -q https://github.com/juanfont/headscale/releases/download/v${RELEASE}/headscale_${RELEASE}_linux_arm64.deb
|
||||||
dpkg -i headscale_${RELEASE}_linux_amd64.deb
|
dpkg -i headscale_${RELEASE}_linux_arm64.deb
|
||||||
rm headscale_${RELEASE}_linux_amd64.deb
|
rm headscale_${RELEASE}_linux_arm64.deb
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to ${RELEASE}"
|
msg_ok "Updated $APP to ${RELEASE}"
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Updating Home Assistant"
|
msg_info "Updating Home Assistant"
|
||||||
source /srv/homeassistant/bin/activate
|
source /srv/homeassistant/bin/activate
|
||||||
pip install ${BR}--upgrade homeassistant &>/dev/null
|
uv pip install ${BR}--upgrade homeassistant &>/dev/null
|
||||||
msg_ok "Updated Home Assistant"
|
msg_ok "Updated Home Assistant"
|
||||||
|
|
||||||
msg_info "Starting Home Assistant"
|
msg_info "Starting Home Assistant"
|
||||||
@@ -121,7 +121,7 @@ function update_script() {
|
|||||||
else
|
else
|
||||||
filebrowser config init -a '0.0.0.0' &>/dev/null
|
filebrowser config init -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser config set -a '0.0.0.0' &>/dev/null
|
filebrowser config set -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser users add admin changeme --perm.admin &>/dev/null
|
filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null
|
||||||
fi
|
fi
|
||||||
msg_ok "Installed FileBrowser"
|
msg_ok "Installed FileBrowser"
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ WantedBy=default.target" >$service_path
|
|||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "FileBrowser should be reachable by going to the following URL.
|
echo -e "FileBrowser should be reachable by going to the following URL.
|
||||||
${BL}http://$IP:8080${CL} admin|changeme\n"
|
${BL}http://$IP:8080${CL} admin|helper-scripts.com\n"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -105,7 +105,7 @@ function update_script() {
|
|||||||
curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/v2.23.0/linux-arm64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null
|
curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/v2.23.0/linux-arm64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null
|
||||||
filebrowser config init -a '0.0.0.0' &>/dev/null
|
filebrowser config init -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser config set -a '0.0.0.0' &>/dev/null
|
filebrowser config set -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser users add admin changeme --perm.admin &>/dev/null
|
filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null
|
||||||
msg_ok "Installed FileBrowser"
|
msg_ok "Installed FileBrowser"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
@@ -125,7 +125,7 @@ WantedBy=default.target" >$service_path
|
|||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "FileBrowser should be reachable by going to the following URL.
|
echo -e "FileBrowser should be reachable by going to the following URL.
|
||||||
${BL}http://$IP:8080${CL} admin|changeme\n"
|
${BL}http://$IP:8080${CL} admin|helper-scripts.com\n"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
__ __ ____
|
||||||
|
/ / / /___ ____ ___ ___ / __ )____ _ __
|
||||||
|
/ /_/ / __ \/ __ `__ \/ _ \/ __ / __ \| |/_/
|
||||||
|
/ __ / /_/ / / / / / / __/ /_/ / /_/ /> <
|
||||||
|
/_/ /_/\____/_/ /_/ /_/\___/_____/\____/_/|_|
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="HomeBox"
|
||||||
|
var_disk="4"
|
||||||
|
var_cpu="1"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -f /opt/homebox ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/sysadminsmedia/homebox/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop homebox
|
||||||
|
msg_ok "${APP} Stopped"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cd /opt
|
||||||
|
rm -rf homebox_bak
|
||||||
|
mv homebox homebox_bak
|
||||||
|
wget -qO- https://github.com/sysadminsmedia/homebox/releases/download/${RELEASE}/homebox_Linux_x86_64.tar.gz | tar -xzf - -C /opt
|
||||||
|
chmod +x /opt/homebox
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated Homebox"
|
||||||
|
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start homebox
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:7745${CL} \n"
|
||||||
+1
-1
@@ -30,7 +30,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
|
|||||||
+36
-8
@@ -20,7 +20,7 @@ header_info
|
|||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="Jellyseerr"
|
APP="Jellyseerr"
|
||||||
var_disk="8"
|
var_disk="8"
|
||||||
var_cpu="2"
|
var_cpu="4"
|
||||||
var_ram="4096"
|
var_ram="4096"
|
||||||
var_os="debian"
|
var_os="debian"
|
||||||
var_version="12"
|
var_version="12"
|
||||||
@@ -55,19 +55,46 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/jellyseerr ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/jellyseerr ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your Jellyseerr LXC to 4vcpu and 4096RAM for the build process before continuing" 10 75
|
||||||
|
if ! command -v pnpm &> /dev/null; then
|
||||||
|
msg_error "pnpm not found. Installing..."
|
||||||
|
npm install -g pnpm &>/dev/null
|
||||||
|
else
|
||||||
|
msg_ok "pnpm is already installed."
|
||||||
|
fi
|
||||||
msg_info "Updating $APP"
|
msg_info "Updating $APP"
|
||||||
systemctl stop jellyseerr
|
|
||||||
cd /opt/jellyseerr
|
cd /opt/jellyseerr
|
||||||
output=$(git pull)
|
output=$(git pull --no-rebase)
|
||||||
git pull &>/dev/null
|
|
||||||
if echo "$output" | grep -q "Already up to date."
|
if echo "$output" | grep -q "Already up to date."
|
||||||
then
|
then
|
||||||
msg_ok " $APP is already up to date."
|
msg_ok "$APP is already up to date."
|
||||||
systemctl start jellyseerr
|
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
yarn install &>/dev/null
|
systemctl stop jellyseerr
|
||||||
yarn build &>/dev/null
|
export CYPRESS_INSTALL_BINARY=0
|
||||||
|
pnpm install --frozen-lockfile &>/dev/null
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
|
pnpm build &>/dev/null
|
||||||
|
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
||||||
|
[Unit]
|
||||||
|
Description=jellyseerr Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=/etc/jellyseerr/jellyseerr.conf
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
Type=exec
|
||||||
|
WorkingDirectory=/opt/jellyseerr
|
||||||
|
ExecStart=/usr/bin/node dist/index.js
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
systemctl start jellyseerr
|
systemctl start jellyseerr
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated $APP"
|
||||||
exit
|
exit
|
||||||
@@ -79,6 +106,7 @@ description
|
|||||||
|
|
||||||
msg_info "Setting Container to Normal Resources"
|
msg_info "Setting Container to Normal Resources"
|
||||||
pct set $CTID -memory 2048
|
pct set $CTID -memory 2048
|
||||||
|
pct set $CTID -cores 2
|
||||||
msg_ok "Set Container to Normal Resources"
|
msg_ok "Set Container to Normal Resources"
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
|
|||||||
+25
-1
@@ -57,8 +57,32 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/keycloak.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/keycloak.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP} LXC"
|
||||||
|
|
||||||
|
msg_info "Updating packages"
|
||||||
apt-get update &>/dev/null
|
apt-get update &>/dev/null
|
||||||
apt-get -y upgrade &>/dev/null
|
apt-get -y upgrade &>/dev/null
|
||||||
|
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/keycloak/keycloak/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
|
msg_info "Downloading Keycloak v$RELEASE"
|
||||||
|
cd /opt
|
||||||
|
wget -q https://github.com/keycloak/keycloak/releases/download/$RELEASE/keycloak-$RELEASE.tar.gz
|
||||||
|
$STD tar -xvf keycloak-$RELEASE.tar.gz
|
||||||
|
|
||||||
|
msg_info "Merging configuration files"
|
||||||
|
cp -r keycloak/conf keycloak-$RELEASE
|
||||||
|
cp -r keycloak/providers keycloak-$RELEASE
|
||||||
|
cp -r keycloak/themes keycloak-$RELEASE
|
||||||
|
|
||||||
|
msg_info "Updating Keycloak"
|
||||||
|
mv keycloak keycloak.old
|
||||||
|
mv keycloak-$RELEASE keycloak
|
||||||
|
|
||||||
|
msg_info "Delete temporary installation files"
|
||||||
|
rm keycloak-$RELEASE.tar.gz
|
||||||
|
rm -rf keycloak.old
|
||||||
|
|
||||||
|
msg_info "Restating Keycloak"
|
||||||
|
systemctl restart keycloak
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
@@ -69,4 +93,4 @@ description
|
|||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${APP} should be reachable by going to the following URL.
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
${BL}http://${IP}:8080${CL} \n"
|
${BL}http://${IP}:8080/admin${CL} \n"
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}
|
|||||||
git pull
|
git pull
|
||||||
yarn
|
yarn
|
||||||
npx playwright install-deps
|
npx playwright install-deps
|
||||||
|
yarn playwright install
|
||||||
yarn prisma generate
|
yarn prisma generate
|
||||||
yarn build
|
yarn build
|
||||||
yarn prisma migrate deploy
|
yarn prisma migrate deploy
|
||||||
|
|||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# # Copyright (c) 2021-2024 tteck
|
||||||
|
# # Author: tteck (tteckster)
|
||||||
|
# # Co-Author: remz1337
|
||||||
|
# # License: MIT
|
||||||
|
# # https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
echo "Unsupported."
|
||||||
|
|
||||||
|
# function header_info {
|
||||||
|
# clear
|
||||||
|
# cat <<"EOF"
|
||||||
|
# ____ __
|
||||||
|
# / / /___/ /___ _____
|
||||||
|
# / / / __ / __ `/ __ \
|
||||||
|
# / / / /_/ / /_/ / /_/ /
|
||||||
|
# /_/_/\__,_/\__,_/ .___/
|
||||||
|
# /_/
|
||||||
|
|
||||||
|
# EOF
|
||||||
|
# }
|
||||||
|
# header_info
|
||||||
|
# echo -e "Loading..."
|
||||||
|
# APP="lldap"
|
||||||
|
# var_disk="4"
|
||||||
|
# var_cpu="1"
|
||||||
|
# var_ram="512"
|
||||||
|
# var_os="debian"
|
||||||
|
# var_version="12"
|
||||||
|
# variables
|
||||||
|
# color
|
||||||
|
# catch_errors
|
||||||
|
|
||||||
|
# function default_settings() {
|
||||||
|
# CT_TYPE="1"
|
||||||
|
# PW=""
|
||||||
|
# CT_ID=$NEXTID
|
||||||
|
# HN=$NSAPP
|
||||||
|
# DISK_SIZE="$var_disk"
|
||||||
|
# CORE_COUNT="$var_cpu"
|
||||||
|
# RAM_SIZE="$var_ram"
|
||||||
|
# BRG="vmbr0"
|
||||||
|
# NET="dhcp"
|
||||||
|
# GATE=""
|
||||||
|
# APT_CACHER=""
|
||||||
|
# APT_CACHER_IP=""
|
||||||
|
# DISABLEIP6="no"
|
||||||
|
# MTU=""
|
||||||
|
# SD=""
|
||||||
|
# NS=""
|
||||||
|
# MAC=""
|
||||||
|
# VLAN=""
|
||||||
|
# SSH="no"
|
||||||
|
# VERB="no"
|
||||||
|
# echo_default
|
||||||
|
# }
|
||||||
|
|
||||||
|
# function update_script() {
|
||||||
|
# header_info
|
||||||
|
# if [[ ! -f /etc/systemd/system/lldap.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
# msg_info "Updating $APP"
|
||||||
|
# apt update
|
||||||
|
# apt upgrade -y lldap
|
||||||
|
# msg_ok "Updated $APP"
|
||||||
|
# exit
|
||||||
|
# }
|
||||||
|
|
||||||
|
# start
|
||||||
|
# build_container
|
||||||
|
# description
|
||||||
|
|
||||||
|
# msg_ok "Completed Successfully!\n"
|
||||||
|
# echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
# ${BL}http://${IP}:17170${CL} \n"
|
||||||
+1
-1
@@ -55,7 +55,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/mafl ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/mafl ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/hywax/mafl/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
RELEASE=$(curl -s https://api.github.com/repos/hywax/mafl/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
msg_info "Updating Mafl to v${RELEASE} (Patience)"
|
msg_info "Updating Mafl to v${RELEASE} (Patience)"
|
||||||
systemctl stop mafl
|
systemctl stop mafl
|
||||||
|
|||||||
+2
-31
@@ -54,37 +54,8 @@ function default_settings() {
|
|||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/matterbridge ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /root/Matterbridge ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_error "Update via the Matterbridge UI"
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/Luligu/matterbridge/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3)}')
|
|
||||||
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
|
||||||
msg_info "Stopping ${APP} Service"
|
|
||||||
systemctl stop matterbridge
|
|
||||||
msg_ok "Stopped ${APP} Service"
|
|
||||||
|
|
||||||
msg_info "Updating ${APP} to ${RELEASE}"
|
|
||||||
cd /opt/matterbridge
|
|
||||||
wget -q "https://github.com/Luligu/matterbridge/archive/refs/tags/${RELEASE}.zip"
|
|
||||||
unzip -q ${RELEASE}.zip
|
|
||||||
mv matterbridge-${RELEASE} /opt/matterbridge
|
|
||||||
cd /opt/matterbridge
|
|
||||||
npm ci >/dev/null 2>&1
|
|
||||||
npm run build >/dev/null 2>&1
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
|
||||||
msg_ok "Updated ${APP} to ${RELEASE}"
|
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
|
||||||
rm /opt/${RELEASE}.zip
|
|
||||||
msg_ok "Cleaned"
|
|
||||||
|
|
||||||
msg_info "Starting ${APP} Service"
|
|
||||||
systemctl start matterbridge
|
|
||||||
sleep 1
|
|
||||||
msg_ok "Started ${APP} Service"
|
|
||||||
msg_ok "Updated Successfully!\n"
|
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
|
||||||
fi
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
__ ___
|
||||||
|
/ |/ /__ ____ ___ ____ _____
|
||||||
|
/ /|_/ / _ \/ __ `__ \/ __ \/ ___/
|
||||||
|
/ / / / __/ / / / / / /_/ (__ )
|
||||||
|
/_/ /_/\___/_/ /_/ /_/\____/____/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Memos"
|
||||||
|
var_disk="7"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="2048"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/memos ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_info "Updating $APP (Patience)"
|
||||||
|
cd /opt/memos
|
||||||
|
output=$(git pull --no-rebase)
|
||||||
|
if echo "$output" | grep -q "Already up to date."
|
||||||
|
then
|
||||||
|
msg_ok "$APP is already up to date."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
systemctl stop memos
|
||||||
|
cd /opt/memos/web
|
||||||
|
pnpm i --frozen-lockfile &>/dev/null
|
||||||
|
pnpm build &>/dev/null
|
||||||
|
cd /opt/memos
|
||||||
|
mkdir -p /opt/memos/server/dist
|
||||||
|
cp -r web/dist/* /opt/memos/server/dist/
|
||||||
|
cp -r web/dist/* /opt/memos/server/router/frontend/dist/
|
||||||
|
go build -o /opt/memos/memos -tags=embed bin/memos/main.go &>/dev/null
|
||||||
|
systemctl start memos
|
||||||
|
msg_ok "Updated $APP"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:9030${CL} \n"
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# # Copyright (c) 2021-2024 tteck
|
||||||
|
# # Author: tteck
|
||||||
|
# # Co-Author: MickLesk (Canbiz)
|
||||||
|
# # License: MIT
|
||||||
|
# # https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
echo "Unsupported."
|
||||||
|
|
||||||
|
# function header_info {
|
||||||
|
# clear
|
||||||
|
# cat <<"EOF"
|
||||||
|
# __ ___ _____ ____ __
|
||||||
|
# / |/ /_ __/ ___// __ \ / /
|
||||||
|
# / /|_/ / / / /\__ \/ / / / / /
|
||||||
|
# / / / / /_/ /___/ / /_/ / / /___
|
||||||
|
# /_/ /_/\__, //____/\___\_\/_____/
|
||||||
|
# /____/
|
||||||
|
# EOF
|
||||||
|
# }
|
||||||
|
# header_info
|
||||||
|
# echo -e "Loading..."
|
||||||
|
# APP="MySQL"
|
||||||
|
# var_disk="4"
|
||||||
|
# var_cpu="1"
|
||||||
|
# var_ram="1024"
|
||||||
|
# var_os="debian"
|
||||||
|
# var_version="12"
|
||||||
|
# variables
|
||||||
|
# color
|
||||||
|
# catch_errors
|
||||||
|
|
||||||
|
# function default_settings() {
|
||||||
|
# CT_TYPE="1"
|
||||||
|
# PW=""
|
||||||
|
# CT_ID=$NEXTID
|
||||||
|
# HN=$NSAPP
|
||||||
|
# DISK_SIZE="$var_disk"
|
||||||
|
# CORE_COUNT="$var_cpu"
|
||||||
|
# RAM_SIZE="$var_ram"
|
||||||
|
# BRG="vmbr0"
|
||||||
|
# NET="dhcp"
|
||||||
|
# GATE=""
|
||||||
|
# APT_CACHER=""
|
||||||
|
# APT_CACHER_IP=""
|
||||||
|
# DISABLEIP6="no"
|
||||||
|
# MTU=""
|
||||||
|
# SD=""
|
||||||
|
# NS=""
|
||||||
|
# MAC=""
|
||||||
|
# VLAN=""
|
||||||
|
# SSH="no"
|
||||||
|
# VERB="no"
|
||||||
|
# echo_default
|
||||||
|
# }
|
||||||
|
|
||||||
|
# function update_script() {
|
||||||
|
# header_info
|
||||||
|
# if [[ ! -f /usr/share/keyrings/mysql.gpg ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
# msg_info "Updating ${APP} LXC"
|
||||||
|
# apt-get update &>/dev/null
|
||||||
|
# apt-get -y upgrade &>/dev/null
|
||||||
|
# msg_ok "Updated Successfully"
|
||||||
|
# exit
|
||||||
|
# }
|
||||||
|
|
||||||
|
# start
|
||||||
|
# build_container
|
||||||
|
# description
|
||||||
|
|
||||||
|
# msg_ok "Completed Successfully!\n"
|
||||||
@@ -65,6 +65,7 @@ if [[ ! -f /etc/systemd/system/n8n.service ]]; then msg_error "No ${APP} Install
|
|||||||
fi
|
fi
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP} LXC"
|
||||||
npm update -g n8n &>/dev/null
|
npm update -g n8n &>/dev/null
|
||||||
|
systemctl restart n8n
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-14
@@ -1,29 +1,30 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
# Copyright (c) 2021-2024 tteck
|
# Copyright (c) 2021-2024 tteck
|
||||||
# Author: tteck (tteckster)
|
# Author: tteck
|
||||||
|
# Co-Author: havardthom
|
||||||
# License: MIT
|
# License: MIT
|
||||||
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
function header_info {
|
function header_info {
|
||||||
clear
|
clear
|
||||||
cat <<"EOF"
|
cat <<"EOF"
|
||||||
__ ____ __ __ __ __
|
_ __ __ __ _
|
||||||
/ /__/ __ \_____ / //_/_ __/ /_ ___ _________ ___ / /____ _____
|
/ | / /__ ____ / // / (_)
|
||||||
/ //_/ / / / ___/ / ,< / / / / __ \/ _ \/ ___/ __ \/ _ \/ __/ _ \/ ___/
|
/ |/ / _ \/ __ \/ // /_/ /
|
||||||
/ ,< / /_/ (__ ) / /| / /_/ / /_/ / __/ / / / / / __/ /_/ __(__ )
|
/ /| / __/ /_/ /__ __/ /
|
||||||
/_/|_|\____/____/ /_/ |_\__,_/_.___/\___/_/ /_/ /_/\___/\__/\___/____/
|
/_/ |_/\___/\____/ /_/_/ /
|
||||||
|
/___/
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
header_info
|
header_info
|
||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="k0s"
|
APP="Neo4j"
|
||||||
var_disk="4"
|
var_disk="4"
|
||||||
var_cpu="2"
|
var_cpu="1"
|
||||||
var_ram="2048"
|
var_ram="1024"
|
||||||
var_os="debian"
|
var_os="debian"
|
||||||
var_version="11"
|
var_version="12"
|
||||||
variables
|
variables
|
||||||
color
|
color
|
||||||
catch_errors
|
catch_errors
|
||||||
@@ -54,8 +55,8 @@ function default_settings() {
|
|||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/k0s/k0s.yaml ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /etc/neo4j ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP}"
|
||||||
apt-get update &>/dev/null
|
apt-get update &>/dev/null
|
||||||
apt-get -y upgrade &>/dev/null
|
apt-get -y upgrade &>/dev/null
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
@@ -67,3 +68,5 @@ build_container
|
|||||||
description
|
description
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Browser should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:7474${CL} \n"
|
||||||
@@ -23,8 +23,8 @@ APP="Nginx Proxy Manager"
|
|||||||
var_disk="4"
|
var_disk="4"
|
||||||
var_cpu="2"
|
var_cpu="2"
|
||||||
var_ram="1024"
|
var_ram="1024"
|
||||||
var_os="ubuntu"
|
var_os="debian"
|
||||||
var_version="22.04"
|
var_version="12"
|
||||||
variables
|
variables
|
||||||
color
|
color
|
||||||
catch_errors
|
catch_errors
|
||||||
@@ -61,7 +61,7 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
if ! command -v pnpm &> /dev/null; then
|
if ! command -v pnpm &> /dev/null; then
|
||||||
msg_info "Installing pnpm"
|
msg_info "Installing pnpm"
|
||||||
export NODE_OPTIONS=--openssl-legacy-provider
|
#export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
npm install -g pnpm@8.15 &>/dev/null
|
npm install -g pnpm@8.15 &>/dev/null
|
||||||
msg_ok "Installed pnpm"
|
msg_ok "Installed pnpm"
|
||||||
fi
|
fi
|
||||||
@@ -168,6 +168,7 @@ EOF
|
|||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
sed -i 's/user npm/user root/g; s/^pid/#pid/g' /usr/local/openresty/nginx/conf/nginx.conf
|
||||||
|
sed -i 's/su npm npm/su root root/g' /etc/logrotate.d/nginx-proxy-manager
|
||||||
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
|
sed -i 's/include-system-site-packages = false/include-system-site-packages = true/g' /opt/certbot/pyvenv.cfg
|
||||||
systemctl enable -q --now openresty
|
systemctl enable -q --now openresty
|
||||||
systemctl enable -q --now npm
|
systemctl enable -q --now npm
|
||||||
@@ -185,9 +186,6 @@ start
|
|||||||
build_container
|
build_container
|
||||||
description
|
description
|
||||||
|
|
||||||
msg_info "Setting Container to Normal Resources"
|
|
||||||
pct set $CTID -cores 1
|
|
||||||
msg_ok "Set Container to Normal Resources"
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${APP} should be reachable by going to the following URL.
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
${BL}http://${IP}:81${CL}\n"
|
${BL}http://${IP}:81${CL}\n"
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: havardthom
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
_ _______ ____ ______ __
|
||||||
|
/ | / /__ / / __ )/ ____/__ / /_
|
||||||
|
/ |/ / / / / __ / / __/ _ \/ __/
|
||||||
|
/ /| / / /__/ /_/ / /_/ / __/ /_
|
||||||
|
/_/ |_/ /____/_____/\____/\___/\__/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="NZBGet"
|
||||||
|
var_disk="4"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="2048"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -f /lib/systemd/system/nzbget.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_info "Updating $APP LXC"
|
||||||
|
apt-get update &>/dev/null
|
||||||
|
apt-get -y upgrade &>/dev/null
|
||||||
|
msg_ok "Updated $APP LXC"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:6789${CL} \n"
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: havardthom
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
____ ____
|
||||||
|
/ __ \/ / /___ _____ ___ ____ _
|
||||||
|
/ / / / / / __ `/ __ `__ \/ __ `/
|
||||||
|
/ /_/ / / / /_/ / / / / / / /_/ /
|
||||||
|
\____/_/_/\__,_/_/ /_/ /_/\__,_/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Ollama"
|
||||||
|
var_disk="24"
|
||||||
|
var_cpu="4"
|
||||||
|
var_ram="4096"
|
||||||
|
var_os="ubuntu"
|
||||||
|
var_version="22.04"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/ollama ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_info "Updating ${APP}"
|
||||||
|
apt-get update &>/dev/null
|
||||||
|
apt-get -y upgrade &>/dev/null
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:11434${CL} \n"
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: havardthom
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
____ _ __ __ __ ______
|
||||||
|
/ __ \____ ___ ____ | | / /__ / /_ / / / / _/
|
||||||
|
/ / / / __ \/ _ \/ __ \ | | /| / / _ \/ __ \/ / / // /
|
||||||
|
/ /_/ / /_/ / __/ / / / | |/ |/ / __/ /_/ / /_/ // /
|
||||||
|
\____/ .___/\___/_/ /_/ |__/|__/\___/_.___/\____/___/
|
||||||
|
/_/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Open WebUI"
|
||||||
|
var_disk="16"
|
||||||
|
var_cpu="4"
|
||||||
|
var_ram="4096"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/open-webui ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
msg_info "Updating ${APP} (Patience)"
|
||||||
|
cd /opt/open-webui
|
||||||
|
output=$(git pull --no-rebase)
|
||||||
|
if echo "$output" | grep -q "Already up to date."
|
||||||
|
then
|
||||||
|
msg_ok "$APP is already up to date."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
systemctl stop open-webui.service
|
||||||
|
npm install &>/dev/null
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3584"
|
||||||
|
npm run build &>/dev/null
|
||||||
|
cd ./backend
|
||||||
|
pip install -r requirements.txt -U &>/dev/null
|
||||||
|
systemctl start open-webui.service
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:8080${CL} \n"
|
||||||
+1
-1
@@ -21,7 +21,7 @@ echo -e "Loading..."
|
|||||||
APP="Overseerr"
|
APP="Overseerr"
|
||||||
var_disk="8"
|
var_disk="8"
|
||||||
var_cpu="2"
|
var_cpu="2"
|
||||||
var_ram="2048"
|
var_ram="3072"
|
||||||
var_os="debian"
|
var_os="debian"
|
||||||
var_version="12"
|
var_version="12"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@@ -67,6 +67,18 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
if [ "$UPD" == "1" ]; then
|
if [ "$UPD" == "1" ]; then
|
||||||
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
||||||
|
if [[ "$(gs --version 2>/dev/null)" != "10.04.0" ]]; then
|
||||||
|
msg_info "Updating Ghostscript"
|
||||||
|
cd /tmp
|
||||||
|
wget -q https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10040/ghostscript-10.04.0.tar.gz
|
||||||
|
tar -xzf ghostscript-10.04.0.tar.gz
|
||||||
|
cd ghostscript-10.04.0
|
||||||
|
./configure &>/dev/null
|
||||||
|
make &>/dev/null
|
||||||
|
sudo make install &>/dev/null
|
||||||
|
rm -rf /tmp/ghostscript*
|
||||||
|
msg_ok "Ghostscript updated to 10.04.0"
|
||||||
|
fi
|
||||||
msg_info "Stopping all Paperless-ngx Services"
|
msg_info "Stopping all Paperless-ngx Services"
|
||||||
systemctl stop paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue.service
|
systemctl stop paperless-consumer paperless-webserver paperless-scheduler paperless-task-queue.service
|
||||||
msg_ok "Stopped all Paperless-ngx Services"
|
msg_ok "Stopped all Paperless-ngx Services"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/peanut.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/peanut.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
RELEASE=$(curl -sL https://api.github.com/repos/Brandawg93/PeaNUT/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
|
RELEASE=$(curl -sL https://api.github.com/repos/Brandawg93/PeaNUT/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
|
||||||
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
msg_info "Updating $APP to ${RELEASE}"
|
msg_info "Updating $APP to ${RELEASE}"
|
||||||
@@ -66,6 +67,8 @@ function update_script() {
|
|||||||
pnpm i &>/dev/null
|
pnpm i &>/dev/null
|
||||||
pnpm run build &>/dev/null
|
pnpm run build &>/dev/null
|
||||||
cp -r .next/static .next/standalone/.next/
|
cp -r .next/static .next/standalone/.next/
|
||||||
|
mkdir -p /opt/peanut/.next/standalone/config
|
||||||
|
ln -sf /etc/peanut/settings.yml /opt/peanut/.next/standalone/config/settings.yml
|
||||||
systemctl start peanut
|
systemctl start peanut
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to ${RELEASE}"
|
msg_ok "Updated $APP to ${RELEASE}"
|
||||||
|
|||||||
+4
-2
@@ -56,7 +56,7 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/pingvin-share ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/pingvin-share ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Stopping Pingvin Share"
|
msg_info "Stopping Pingvin Share"
|
||||||
pm2 stop pingvin-share-backend pingvin-share-frontend &>/dev/null
|
systemctl stop pm2-root.service
|
||||||
msg_ok "Stopped Pingvin Share"
|
msg_ok "Stopped Pingvin Share"
|
||||||
|
|
||||||
msg_info "Updating Pingvin Share"
|
msg_info "Updating Pingvin Share"
|
||||||
@@ -64,13 +64,15 @@ cd /opt/pingvin-share
|
|||||||
git fetch --tags
|
git fetch --tags
|
||||||
git checkout $(git describe --tags `git rev-list --tags --max-count=1`) &>/dev/null
|
git checkout $(git describe --tags `git rev-list --tags --max-count=1`) &>/dev/null
|
||||||
cd backend
|
cd backend
|
||||||
|
npm install &>/dev/null
|
||||||
npm run build &>/dev/null
|
npm run build &>/dev/null
|
||||||
cd ../frontend
|
cd ../frontend
|
||||||
|
npm install &>/dev/null
|
||||||
npm run build &>/dev/null
|
npm run build &>/dev/null
|
||||||
msg_ok "Updated Pingvin Share"
|
msg_ok "Updated Pingvin Share"
|
||||||
|
|
||||||
msg_info "Starting Pingvin Share"
|
msg_info "Starting Pingvin Share"
|
||||||
pm2 start pingvin-share-backend pingvin-share-frontend &>/dev/null
|
systemctl start pm2-root.service
|
||||||
msg_ok "Started Pingvin Share"
|
msg_ok "Started Pingvin Share"
|
||||||
|
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ if [ "$UPD" == "3" ]; then
|
|||||||
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash &>/dev/null
|
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash &>/dev/null
|
||||||
filebrowser config init -a '0.0.0.0' &>/dev/null
|
filebrowser config init -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser config set -a '0.0.0.0' &>/dev/null
|
filebrowser config set -a '0.0.0.0' &>/dev/null
|
||||||
filebrowser users add admin changeme --perm.admin &>/dev/null
|
filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null
|
||||||
msg_ok "Installed FileBrowser"
|
msg_ok "Installed FileBrowser"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
@@ -122,7 +122,7 @@ if [ "$UPD" == "3" ]; then
|
|||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "FileBrowser should be reachable by going to the following URL.
|
echo -e "FileBrowser should be reachable by going to the following URL.
|
||||||
${BL}http://$IP:8080${CL} admin|changeme\n"
|
${BL}http://$IP:8080${CL} admin|helper-scripts.com\n"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
if [ "$UPD" == "4" ]; then
|
if [ "$UPD" == "4" ]; then
|
||||||
|
|||||||
+23
-1
@@ -55,7 +55,29 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/prometheus.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/prometheus.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_error "There is currently no update path available."
|
RELEASE=$(curl -s https://api.github.com/repos/prometheus/prometheus/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop prometheus
|
||||||
|
msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
wget -q https://github.com/prometheus/prometheus/releases/download/v${RELEASE}/prometheus-${RELEASE}.linux-amd64.tar.gz
|
||||||
|
tar -xf prometheus-${RELEASE}.linux-amd64.tar.gz
|
||||||
|
cd prometheus-${RELEASE}.linux-amd64
|
||||||
|
cp -rf prometheus promtool /usr/local/bin/
|
||||||
|
cd ~
|
||||||
|
rm -rf prometheus-${RELEASE}.linux-amd64 prometheus-${RELEASE}.linux-amd64.tar.gz
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start prometheus
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-4
@@ -55,10 +55,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /var/lib/radarr/ ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /var/lib/radarr/ ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating $APP LXC"
|
msg_error "There is currently no update path available."
|
||||||
apt-get update &>/dev/null
|
|
||||||
apt-get -y upgrade &>/dev/null
|
|
||||||
msg_ok "Updated $APP LXC"
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-9
@@ -55,16 +55,21 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/sabnzbd ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/sabnzbd ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating $APP"
|
|
||||||
systemctl stop sabnzbd.service
|
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
RELEASE=$(curl -s https://api.github.com/repos/sabnzbd/sabnzbd/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
tar zxvf <(curl -fsSL https://github.com/sabnzbd/sabnzbd/releases/download/$RELEASE/SABnzbd-${RELEASE}-src.tar.gz) &>/dev/null
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
\cp -r SABnzbd-${RELEASE}/* /opt/sabnzbd &>/dev/null
|
msg_info "Updating $APP to ${RELEASE}"
|
||||||
rm -rf SABnzbd-${RELEASE}
|
systemctl stop sabnzbd.service
|
||||||
cd /opt/sabnzbd
|
tar zxvf <(curl -fsSL https://github.com/sabnzbd/sabnzbd/releases/download/$RELEASE/SABnzbd-${RELEASE}-src.tar.gz) &>/dev/null
|
||||||
python3 -m pip install -r requirements.txt &>/dev/null
|
\cp -r SABnzbd-${RELEASE}/* /opt/sabnzbd &>/dev/null
|
||||||
systemctl start sabnzbd.service
|
rm -rf SABnzbd-${RELEASE}
|
||||||
msg_ok "Updated $APP"
|
cd /opt/sabnzbd
|
||||||
|
python3 -m pip install -r requirements.txt &>/dev/null
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
systemctl start sabnzbd.service
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
else
|
||||||
|
msg_info "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
|
|||||||
+2
-2
@@ -71,10 +71,10 @@ if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_v
|
|||||||
rm -rf spoolman_bak
|
rm -rf spoolman_bak
|
||||||
mv spoolman spoolman_bak
|
mv spoolman spoolman_bak
|
||||||
wget -q https://github.com/Donkie/Spoolman/releases/download/${RELEASE}/spoolman.zip
|
wget -q https://github.com/Donkie/Spoolman/releases/download/${RELEASE}/spoolman.zip
|
||||||
unzip -q spoolman.zip -d spoolman
|
unzip -q spoolman.zip -d spoolman
|
||||||
cd spoolman
|
cd spoolman
|
||||||
pip3 install -r requirements.txt >/dev/null 2>&1
|
pip3 install -r requirements.txt >/dev/null 2>&1
|
||||||
cp .env.example .env
|
wget -q https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example -O .env
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to ${RELEASE}"
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function default_settings() {
|
function default_settings() {
|
||||||
CT_TYPE="1"
|
CT_TYPE="0"
|
||||||
PW=""
|
PW=""
|
||||||
CT_ID=$NEXTID
|
CT_ID=$NEXTID
|
||||||
HN=$NSAPP
|
HN=$NSAPP
|
||||||
|
|||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
_______ _ _
|
||||||
|
/_ __(_)___ _____ (_|_)
|
||||||
|
/ / / / __ `/ __ \ / / /
|
||||||
|
/ / / / /_/ / / / / / / /
|
||||||
|
/_/ /_/\__,_/_/ /_/_/ /_/
|
||||||
|
/___/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Tianji"
|
||||||
|
var_disk="12"
|
||||||
|
var_cpu="4"
|
||||||
|
var_ram="4096"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/tianji ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/msgbyte/tianji/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
|
msg_info "Stopping ${APP} Service"
|
||||||
|
systemctl stop tianji
|
||||||
|
msg_ok "Stopped ${APP} Service"
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cd /opt
|
||||||
|
cp /opt/tianji/src/server/.env /opt/.env
|
||||||
|
mv /opt/tianji /opt/tianji_bak
|
||||||
|
wget -q "https://github.com/msgbyte/tianji/archive/refs/tags/v${RELEASE}.zip"
|
||||||
|
unzip -q v${RELEASE}.zip
|
||||||
|
mv tianji-${RELEASE} /opt/tianji
|
||||||
|
cd tianji
|
||||||
|
pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile >/dev/null 2>&1
|
||||||
|
pnpm build:static >/dev/null 2>&1
|
||||||
|
pnpm install --filter @tianji/server... --config.dedupe-peer-dependents=false >/dev/null 2>&1
|
||||||
|
mkdir -p ./src/server/public >/dev/null 2>&1
|
||||||
|
cp -r ./geo ./src/server/public >/dev/null 2>&1
|
||||||
|
pnpm build:server >/dev/null 2>&1
|
||||||
|
mv /opt/.env /opt/tianji/src/server/.env
|
||||||
|
cd src/server
|
||||||
|
pnpm db:migrate:apply >/dev/null 2>&1
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start tianji
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -R /opt/v${RELEASE}.zip
|
||||||
|
rm -rf /opt/tianji_bak
|
||||||
|
rm -rf /opt/tianji/src/client
|
||||||
|
rm -rf /opt/tianji/website
|
||||||
|
rm -rf /opt/tianji/reporter
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}."
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_info "Setting Container to Normal Resources"
|
||||||
|
pct set $CTID -memory 1024
|
||||||
|
pct set $CTID -cores 1
|
||||||
|
msg_ok "Set Container to Normal Resources"
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:12345${CL} \n"
|
||||||
+2
-1
@@ -55,13 +55,14 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -f /etc/systemd/system/traefik.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /etc/systemd/system/traefik.service ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/traefik/traefik/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
RELEASE=$(curl -s https://api.github.com/repos/traefik/traefik/releases | grep -oP '"tag_name":\s*"v\K[\d.]+?(?=")' | sort -V | tail -n 1)
|
||||||
msg_info "Updating $APP LXC"
|
msg_info "Updating $APP LXC"
|
||||||
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
||||||
wget -q https://github.com/traefik/traefik/releases/download/v${RELEASE}/traefik_v${RELEASE}_linux_arm64.tar.gz
|
wget -q https://github.com/traefik/traefik/releases/download/v${RELEASE}/traefik_v${RELEASE}_linux_arm64.tar.gz
|
||||||
tar -C /tmp -xzf traefik*.tar.gz
|
tar -C /tmp -xzf traefik*.tar.gz
|
||||||
mv /tmp/traefik /usr/bin/
|
mv /tmp/traefik /usr/bin/
|
||||||
rm -rf traefik*.tar.gz
|
rm -rf traefik*.tar.gz
|
||||||
|
systemctl restart traefik.service
|
||||||
msg_ok "Updated $APP LXC"
|
msg_ok "Updated $APP LXC"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
+8
-10
@@ -1,11 +1,11 @@
|
|||||||
# #!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
# source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
# # Copyright (c) 2021-2024 tteck
|
# # Copyright (c) 2021-2024 tteck
|
||||||
# # Author: tteck (tteckster)
|
# # Author: tteck (tteckster)
|
||||||
# # License: MIT
|
# # License: MIT
|
||||||
# # https://github.com/tteck/Proxmox/raw/main/LICENSE
|
# # https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
echo "Unsupported. View notes on GitHub."
|
echo "Unsupported."
|
||||||
|
|
||||||
# function header_info {
|
# function header_info {
|
||||||
# clear
|
# clear
|
||||||
@@ -57,23 +57,21 @@ echo "Unsupported. View notes on GitHub."
|
|||||||
# function update_script() {
|
# function update_script() {
|
||||||
# header_info
|
# header_info
|
||||||
# if [[ ! -d /opt/trilium ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
# if [[ ! -d /opt/trilium ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
# RELEASE=$(curl -s https://api.github.com/repos/zadam/trilium/releases/latest |
|
# RELEASE=$(curl -s https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
# grep "tag_name" |
|
|
||||||
# awk '{print substr($2, 3, length($2)-4) }')
|
|
||||||
|
|
||||||
# msg_info "Stopping ${APP}"
|
# msg_info "Stopping ${APP}"
|
||||||
# systemctl stop trilium.service
|
# systemctl stop trilium.service
|
||||||
# sleep 1
|
# sleep 1
|
||||||
# msg_ok "Stopped ${APP}"
|
# msg_ok "Stopped ${APP}"
|
||||||
|
|
||||||
# msg_info "Updating to v${RELEASE}"
|
# msg_info "Updating to ${RELEASE}"
|
||||||
# wget -q https://github.com/zadam/trilium/releases/download/v$RELEASE/trilium-linux-x64-server-$RELEASE.tar.xz
|
# wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
|
||||||
# tar -xvf trilium-linux-x64-server-$RELEASE.tar.xz &>/dev/null
|
# tar -xf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
|
||||||
# cp -r trilium-linux-x64-server/* /opt/trilium/
|
# cp -r trilium-linux-x64-server/* /opt/trilium/
|
||||||
# msg_ok "Updated to v${RELEASE}"
|
# msg_ok "Updated to ${RELEASE}"
|
||||||
|
|
||||||
# msg_info "Cleaning up"
|
# msg_info "Cleaning up"
|
||||||
# rm -rf trilium-linux-x64-server-$RELEASE.tar.xz trilium-linux-x64-server
|
# rm -rf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz trilium-linux-x64-server
|
||||||
# msg_ok "Cleaned"
|
# msg_ok "Cleaned"
|
||||||
|
|
||||||
# msg_info "Starting ${APP}"
|
# msg_info "Starting ${APP}"
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/umami ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/umami ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ cat <<"EOF"
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
header_info
|
header_info
|
||||||
|
if ! grep -q -m1 'avx[^ ]*' /proc/cpuinfo; then
|
||||||
|
echo "AVX instruction set is not supported on this CPU."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="Unifi"
|
APP="Unifi"
|
||||||
var_disk="8"
|
var_disk="8"
|
||||||
|
|||||||
+5
-1
@@ -57,6 +57,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VAULT=$(curl -s https://api.github.com/repos/dani-garcia/vaultwarden/releases/latest |
|
VAULT=$(curl -s https://api.github.com/repos/dani-garcia/vaultwarden/releases/latest |
|
||||||
grep "tag_name" |
|
grep "tag_name" |
|
||||||
awk '{print substr($2, 2, length($2)-3) }')
|
awk '{print substr($2, 2, length($2)-3) }')
|
||||||
@@ -72,7 +73,7 @@ function update_script() {
|
|||||||
|
|
||||||
header_info
|
header_info
|
||||||
if [ "$UPD" == "1" ]; then
|
if [ "$UPD" == "1" ]; then
|
||||||
echo -e "\n ⚠️ Ensure you set 4vCPU & 4096MiB RAM minimum!!! \n"
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "SET RESOURCES" "Please set the resources in your ${APP} LXC to ${var_cpu}vCPU and ${var_ram}RAM for the build process before continuing" 10 75
|
||||||
msg_info "Stopping Vaultwarden"
|
msg_info "Stopping Vaultwarden"
|
||||||
systemctl stop vaultwarden.service
|
systemctl stop vaultwarden.service
|
||||||
msg_ok "Stopped Vaultwarden"
|
msg_ok "Stopped Vaultwarden"
|
||||||
@@ -128,6 +129,9 @@ function update_script() {
|
|||||||
if ! command -v argon2 >/dev/null 2>&1; then apt-get install -y argon2 &>/dev/null; fi
|
if ! command -v argon2 >/dev/null 2>&1; then apt-get install -y argon2 &>/dev/null; fi
|
||||||
TOKEN=$(echo -n ${NEWTOKEN} | argon2 "$(openssl rand -base64 32)" -t 2 -m 16 -p 4 -l 64 -e)
|
TOKEN=$(echo -n ${NEWTOKEN} | argon2 "$(openssl rand -base64 32)" -t 2 -m 16 -p 4 -l 64 -e)
|
||||||
sed -i "s|ADMIN_TOKEN=.*|ADMIN_TOKEN='${TOKEN}'|" /opt/vaultwarden/.env
|
sed -i "s|ADMIN_TOKEN=.*|ADMIN_TOKEN='${TOKEN}'|" /opt/vaultwarden/.env
|
||||||
|
if [[ -f /opt/vaultwarden/data/config.json ]]; then
|
||||||
|
sed -i "s|\"admin_token\":.*|\"admin_token\": \"${TOKEN}\"|" /opt/vaultwarden/data/config.json
|
||||||
|
fi
|
||||||
systemctl restart vaultwarden
|
systemctl restart vaultwarden
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/tteck/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
_ __ ____
|
||||||
|
| | / /___ _/ / /___ _____
|
||||||
|
| | /| / / __ `/ / / __ \/ ___/
|
||||||
|
| |/ |/ / /_/ / / / /_/ (__ )
|
||||||
|
|__/|__/\__,_/_/_/\____/____/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Wallos"
|
||||||
|
var_disk="5"
|
||||||
|
var_cpu="1"
|
||||||
|
var_ram="1024"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/wallos ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/ellite/Wallos/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cd /opt
|
||||||
|
wget -q "https://github.com/ellite/Wallos/archive/refs/tags/v${RELEASE}.zip"
|
||||||
|
mv /opt/wallos/db/wallos.db /opt/wallos.db
|
||||||
|
unzip -q v${RELEASE}.zip
|
||||||
|
mv Wallos-${RELEASE} /opt/wallos
|
||||||
|
rm -rf /opt/wallos/db/wallos.empty.db
|
||||||
|
mv /opt/wallos.db /opt/wallos/db/wallos.db
|
||||||
|
chown -R www-data:www-data /opt/wallos
|
||||||
|
chmod -R 755 /opt/wallos
|
||||||
|
curl http://localhost/endpoints/db/migrate.php &>/dev/null
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
|
msg_info "Reload Apache2"
|
||||||
|
systemctl reload apache2
|
||||||
|
msg_ok "Apache2 Reloaded"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -R /opt/v${RELEASE}.zip
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP} ${CL} \n"
|
||||||
+25
-37
@@ -23,8 +23,8 @@ header_info
|
|||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="Wastebin"
|
APP="Wastebin"
|
||||||
var_disk="4"
|
var_disk="4"
|
||||||
var_cpu="4"
|
var_cpu="1"
|
||||||
var_ram="2048"
|
var_ram="1024"
|
||||||
var_os="debian"
|
var_os="debian"
|
||||||
var_version="12"
|
var_version="12"
|
||||||
variables
|
variables
|
||||||
@@ -58,39 +58,31 @@ function default_settings() {
|
|||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/wastebin ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/wastebin ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
|
||||||
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
|
||||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
|
||||||
fi
|
|
||||||
msg_info "Stopping Wastebin"
|
|
||||||
systemctl stop wastebin
|
|
||||||
msg_ok "Wastebin Stopped"
|
|
||||||
|
|
||||||
msg_info "Updating Wastebin"
|
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/matze/wastebin/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
RELEASE=$(curl -s https://api.github.com/repos/matze/wastebin/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
cd /opt
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
if [ -d wastebin_bak ]; then
|
msg_info "Stopping Wastebin"
|
||||||
rm -rf wastebin_bak
|
systemctl stop wastebin
|
||||||
|
msg_ok "Wastebin Stopped"
|
||||||
|
|
||||||
|
msg_info "Updating Wastebin"
|
||||||
|
wget -q https://github.com/matze/wastebin/releases/download/${RELEASE}/wastebin_${RELEASE}_x86_64-unknown-linux-musl.tar.zst
|
||||||
|
tar -xf wastebin_${RELEASE}_x86_64-unknown-linux-musl.tar.zst
|
||||||
|
cp -f wastebin /opt/wastebin/
|
||||||
|
chmod +x /opt/wastebin/wastebin
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated Wastebin"
|
||||||
|
|
||||||
|
msg_info "Starting Wastebin"
|
||||||
|
systemctl start wastebin
|
||||||
|
msg_ok "Started Wastebin"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf wastebin_${RELEASE}_x86_64-unknown-linux-musl.tar.zst
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
fi
|
fi
|
||||||
mv wastebin wastebin_bak
|
|
||||||
wget -q "https://github.com/matze/wastebin/archive/refs/tags/${RELEASE}.zip"
|
|
||||||
unzip -q ${RELEASE}.zip
|
|
||||||
mv wastebin-${RELEASE} /opt/wastebin
|
|
||||||
cd /opt/wastebin
|
|
||||||
cargo update -q
|
|
||||||
cargo build -q --release
|
|
||||||
msg_ok "Updated Wastebin"
|
|
||||||
|
|
||||||
msg_info "Starting Wastebin"
|
|
||||||
systemctl start wastebin
|
|
||||||
msg_ok "Started Wastebin"
|
|
||||||
|
|
||||||
msg_info "Cleaning Up"
|
|
||||||
cd /opt
|
|
||||||
rm -R ${RELEASE}.zip
|
|
||||||
rm -R wastebin_bak
|
|
||||||
msg_ok "Cleaned"
|
|
||||||
msg_ok "Updated Successfully"
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,10 +90,6 @@ start
|
|||||||
build_container
|
build_container
|
||||||
description
|
description
|
||||||
|
|
||||||
msg_info "Setting Container to Normal Resources"
|
|
||||||
pct set $CTID -cores 2
|
|
||||||
msg_ok "Set Container to Normal Resources"
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${APP} Setup should be reachable by going to the following URL.
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
${BL}http://${IP}:8088${CL} \n"
|
${BL}http://${IP}:8088${CL} \n"
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ header_info
|
|||||||
if [[ ! -f /usr/local/bin/whoogle-search ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -f /usr/local/bin/whoogle-search ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP} LXC"
|
||||||
pip3 install whoogle-search --upgrade &>/dev/null
|
pip3 install whoogle-search --upgrade &>/dev/null
|
||||||
|
systemctl restart whoogle.service
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-66
@@ -19,11 +19,11 @@ EOF
|
|||||||
header_info
|
header_info
|
||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="Wireguard"
|
APP="Wireguard"
|
||||||
var_disk="2"
|
var_disk="4"
|
||||||
var_cpu="1"
|
var_cpu="1"
|
||||||
var_ram="512"
|
var_ram="512"
|
||||||
var_os="ubuntu"
|
var_os="debian"
|
||||||
var_version="20.04"
|
var_version="12"
|
||||||
variables
|
variables
|
||||||
color
|
color
|
||||||
catch_errors
|
catch_errors
|
||||||
@@ -53,71 +53,13 @@ function default_settings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
if [[ ! -d /etc/pivpn/wireguard ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /etc/wireguard ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
UPD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUPPORT" --radiolist --cancel-button Exit-Script "Spacebar = Select" 11 58 2 \
|
apt-get update
|
||||||
"1" "Update ${APP} LXC" ON \
|
apt-get -y upgrade
|
||||||
"2" "Install WGDashboard" OFF \
|
sleep 2
|
||||||
3>&1 1>&2 2>&3)
|
|
||||||
header_info
|
|
||||||
if [ "$UPD" == "1" ]; then
|
|
||||||
msg_info "Updating ${APP} LXC"
|
|
||||||
apt-get update &>/dev/null
|
|
||||||
apt-get -y upgrade &>/dev/null
|
|
||||||
msg_ok "Updated ${APP} LXC"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if [ "$UPD" == "2" ]; then
|
|
||||||
if [[ -f /etc/systemd/system/wg-dashboard.service ]]; then
|
|
||||||
cd /etc/wgdashboard/src
|
|
||||||
chmod u+x wgd.sh
|
|
||||||
./wgd.sh update
|
|
||||||
msg_ok "Updated Successfully"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
IP=$(hostname -I | awk '{print $1}')
|
|
||||||
msg_info "Installing Python3-pip"
|
|
||||||
apt-get install -y python3-pip &>/dev/null
|
|
||||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
|
||||||
pip install flask &>/dev/null
|
|
||||||
pip install ifcfg &>/dev/null
|
|
||||||
pip install flask_qrcode &>/dev/null
|
|
||||||
pip install icmplib &>/dev/null
|
|
||||||
msg_ok "Installed Python3-pip"
|
|
||||||
|
|
||||||
msg_info "Installing WGDashboard"
|
|
||||||
WGDREL=$(curl -s https://api.github.com/repos/donaldzou/WGDashboard/releases/latest |
|
|
||||||
grep "tag_name" |
|
|
||||||
awk '{print substr($2, 2, length($2)-3) }')
|
|
||||||
|
|
||||||
git clone -b ${WGDREL} https://github.com/donaldzou/WGDashboard.git /etc/wgdashboard &>/dev/null
|
|
||||||
cd /etc/wgdashboard/src
|
cd /etc/wgdashboard/src
|
||||||
chmod u+x wgd.sh
|
./wgd.sh update
|
||||||
./wgd.sh install &>/dev/null
|
|
||||||
chmod -R 755 /etc/wireguard
|
|
||||||
msg_ok "Installed WGDashboard"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
service_path="/etc/systemd/system/wg-dashboard.service"
|
|
||||||
echo "[Unit]
|
|
||||||
After=systemd-networkd.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
WorkingDirectory=/etc/wgdashboard/src
|
|
||||||
ExecStart=/usr/bin/python3 /etc/wgdashboard/src/dashboard.py
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target" >$service_path
|
|
||||||
chmod 664 /etc/systemd/system/wg-dashboard.service
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable wg-dashboard.service &>/dev/null
|
|
||||||
systemctl start wg-dashboard.service &>/dev/null
|
|
||||||
msg_ok "Created Service"
|
|
||||||
echo -e "WGDashboard should be reachable by going to the following URL.
|
|
||||||
${BL}http://${IP}:10086${CL} admin|admin \n"
|
|
||||||
exit
|
exit
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
@@ -125,3 +67,5 @@ build_container
|
|||||||
description
|
description
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "WGDashboard should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:10086${CL} admin|admin \n"
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ if [[ ! -f /etc/zabbix/zabbix_server.conf ]]; then msg_error "No ${APP} Installa
|
|||||||
msg_info "Updating $APP LXC"
|
msg_info "Updating $APP LXC"
|
||||||
apt-get update &>/dev/null
|
apt-get update &>/dev/null
|
||||||
apt-get -y upgrade &>/dev/null
|
apt-get -y upgrade &>/dev/null
|
||||||
|
systemctl restart zabbix-server
|
||||||
msg_ok "Updated $APP LXC"
|
msg_ok "Updated $APP LXC"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2024 tteck
|
||||||
|
# Author: tteck
|
||||||
|
# Co-Author: MickLesk (Canbiz)
|
||||||
|
# License: MIT
|
||||||
|
# https://github.com/tteck/Proxmox/raw/main/LICENSE
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
_____ _ ___
|
||||||
|
/__ / (_)___ / (_)___ ___
|
||||||
|
/ / / / __ \/ / / __ \/ _ \
|
||||||
|
/ /__/ / /_/ / / / / / / __/
|
||||||
|
/____/_/ .___/_/_/_/ /_/\___/
|
||||||
|
/_/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
header_info
|
||||||
|
echo -e "Loading..."
|
||||||
|
APP="Zipline"
|
||||||
|
var_disk="5"
|
||||||
|
var_cpu="2"
|
||||||
|
var_ram="2048"
|
||||||
|
var_os="debian"
|
||||||
|
var_version="12"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function default_settings() {
|
||||||
|
CT_TYPE="1"
|
||||||
|
PW=""
|
||||||
|
CT_ID=$NEXTID
|
||||||
|
HN=$NSAPP
|
||||||
|
DISK_SIZE="$var_disk"
|
||||||
|
CORE_COUNT="$var_cpu"
|
||||||
|
RAM_SIZE="$var_ram"
|
||||||
|
BRG="vmbr0"
|
||||||
|
NET="dhcp"
|
||||||
|
GATE=""
|
||||||
|
APT_CACHER=""
|
||||||
|
APT_CACHER_IP=""
|
||||||
|
DISABLEIP6="no"
|
||||||
|
MTU=""
|
||||||
|
SD=""
|
||||||
|
NS=""
|
||||||
|
MAC=""
|
||||||
|
VLAN=""
|
||||||
|
SSH="no"
|
||||||
|
VERB="no"
|
||||||
|
echo_default
|
||||||
|
}
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
if [[ ! -d /opt/zipline ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
|
if (( $(df /boot | awk 'NR==2{gsub("%","",$5); print $5}') > 80 )); then
|
||||||
|
read -r -p "Warning: Storage is dangerously low, continue anyway? <y/N> " prompt
|
||||||
|
[[ ${prompt,,} =~ ^(y|yes)$ ]] || exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -s https://api.github.com/repos/diced/zipline/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping ${APP}"
|
||||||
|
systemctl stop zipline
|
||||||
|
msg_ok "${APP} Stopped"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP} to ${RELEASE}"
|
||||||
|
cp /opt/zipline/.env /opt/
|
||||||
|
rm -R /opt/zipline
|
||||||
|
wget -q "https://github.com/diced/zipline/archive/refs/tags/v${RELEASE}.zip"
|
||||||
|
unzip -q v${RELEASE}.zip
|
||||||
|
mv zipline-${RELEASE} /opt/zipline
|
||||||
|
cd /opt/zipline
|
||||||
|
mv /opt/.env /opt/zipline/.env
|
||||||
|
yarn install &>/dev/null
|
||||||
|
yarn build &>/dev/null
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
|
msg_info "Starting ${APP}"
|
||||||
|
systemctl start zipline
|
||||||
|
msg_ok "Started ${APP}"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf v${RELEASE}.zip
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${APP} Setup should be reachable by going to the following URL.
|
||||||
|
${BL}http://${IP}:3000${CL} \n"
|
||||||
+16
-17
@@ -20,7 +20,7 @@ header_info
|
|||||||
echo -e "Loading..."
|
echo -e "Loading..."
|
||||||
APP="Zoraxy"
|
APP="Zoraxy"
|
||||||
var_disk="6"
|
var_disk="6"
|
||||||
var_cpu="4"
|
var_cpu="2"
|
||||||
var_ram="2048"
|
var_ram="2048"
|
||||||
var_os="debian"
|
var_os="debian"
|
||||||
var_version="12"
|
var_version="12"
|
||||||
@@ -54,29 +54,28 @@ function default_settings() {
|
|||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
if [[ ! -d /opt/zoraxy/src ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
if [[ ! -d /opt/zoraxy/ ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
|
||||||
msg_info "Updating $APP"
|
RELEASE=$(curl -s https://api.github.com/repos/tobychui/zoraxy/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
|
||||||
systemctl stop zoraxy
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
cd /opt/zoraxy/src
|
msg_info "Updating $APP to ${RELEASE}"
|
||||||
systemctl stop zoraxy
|
systemctl stop zoraxy
|
||||||
if git pull | grep -q 'Already up to date.'; then
|
wget -q "https://github.com/tobychui/zoraxy/releases/download/${RELEASE}/zoraxy_linux_amd64"
|
||||||
msg_ok "Already up to date. No update required."
|
rm /opt/zoraxy/zoraxy
|
||||||
else
|
mv zoraxy_linux_amd64 /opt/zoraxy/zoraxy
|
||||||
go mod tidy
|
chmod +x /opt/zoraxy/zoraxy
|
||||||
go build
|
systemctl start zoraxy
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated $APP"
|
||||||
fi
|
else
|
||||||
systemctl start zoraxy
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
exit
|
fi
|
||||||
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
build_container
|
build_container
|
||||||
description
|
description
|
||||||
|
|
||||||
msg_info "Setting Container to Normal Resources"
|
|
||||||
pct set $CTID -cores 2
|
|
||||||
msg_ok "Set Container to Normal Resources"
|
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${APP} should be reachable by going to the following URL.
|
echo -e "${APP} should be reachable by going to the following URL.
|
||||||
${BL}http://${IP}:8000${CL} \n"
|
${BL}http://${IP}:8000${CL} \n"
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": ["next/core-web-vitals"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"plugins": ["@typescript-eslint"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# wrangler
|
||||||
|
.worker-next
|
||||||
|
.wrangler
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
out
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# # local env files
|
||||||
|
# .env*.local
|
||||||
|
# .env
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
build
|
||||||
|
.contentlayer
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-organize-imports"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Bram Suurd
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"rsc": true,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.ts",
|
||||||
|
"css": "@/styles/globals.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
webpack: (config) => {
|
||||||
|
config.resolve.alias.canvas = false;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "**",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
env: {
|
||||||
|
BASE_PATH: "ProxmoxVE",
|
||||||
|
},
|
||||||
|
|
||||||
|
output: "export",
|
||||||
|
basePath: `/ProxmoxVE`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
Generated
+10090
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"name": "proxmox-helper-scripts-website",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": true,
|
||||||
|
"author": {
|
||||||
|
"name": "Bram Suurd",
|
||||||
|
"url": "https://github.com/community-scripts"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev --turbopack",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"test": "vitest",
|
||||||
|
"deploy": "next build && touch out/.nojekyll && git add out/ && git commit -m \"Deploy\" && git subtree push --prefix out origin gh-pages",
|
||||||
|
"format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
|
||||||
|
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||||
|
"@radix-ui/react-icons": "^1.3.1",
|
||||||
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-navigation-menu": "^1.1.4",
|
||||||
|
"@radix-ui/react-popover": "^1.1.2",
|
||||||
|
"@radix-ui/react-select": "^2.1.2",
|
||||||
|
"@radix-ui/react-separator": "^1.1.0",
|
||||||
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@radix-ui/react-switch": "^1.1.1",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.0",
|
||||||
|
"@radix-ui/react-tooltip": "^1.1.2",
|
||||||
|
"@vercel/analytics": "^1.2.2",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cmdk": "^1.0.0",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
|
"framer-motion": "^11.11.11",
|
||||||
|
"fuse.js": "^7.0.0",
|
||||||
|
"lucide-react": "^0.453.0",
|
||||||
|
"mini-svg-data-uri": "^1.4.4",
|
||||||
|
"next": "15.1.3",
|
||||||
|
"next-themes": "^0.3.0",
|
||||||
|
"nuqs": "^2.1.1",
|
||||||
|
"pocketbase": "^0.21.4",
|
||||||
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
|
"react": "19.0.0-rc-02c0e824-20241028",
|
||||||
|
"react-code-blocks": "^0.1.6",
|
||||||
|
"react-day-picker": "8.10.1",
|
||||||
|
"react-dom": "19.0.0-rc-02c0e824-20241028",
|
||||||
|
"react-icons": "^5.1.0",
|
||||||
|
"react-simple-typewriter": "^5.0.1",
|
||||||
|
"sharp": "^0.33.5",
|
||||||
|
"simple-icons": "^13.5.0",
|
||||||
|
"sonner": "^1.5.0",
|
||||||
|
"tailwind-merge": "^2.3.0",
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@testing-library/dom": "^10.4.0",
|
||||||
|
"@testing-library/react": "^16.0.1",
|
||||||
|
"@types/node": "^22",
|
||||||
|
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||||
|
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.8.1",
|
||||||
|
"@typescript-eslint/parser": "^8.8.1",
|
||||||
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"eslint-config-next": "15.0.2",
|
||||||
|
"eslint": "^9.13.0",
|
||||||
|
"jsdom": "^25.0.1",
|
||||||
|
"postcss": "^8",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"tailwindcss-animated": "^1.1.2",
|
||||||
|
"tailwindcss": "^3.4.9",
|
||||||
|
"typescript": "^5",
|
||||||
|
"vite-tsconfig-paths": "^5.1.3",
|
||||||
|
"vitest": "^2.1.6"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||||
|
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('postcss-load-config').Config} */
|
||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
@@ -0,0 +1 @@
|
|||||||
|
../../json
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -0,0 +1,11 @@
|
|||||||
|
import { screen } from "@testing-library/dom";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import Page from "@/app/page";
|
||||||
|
|
||||||
|
describe("Page", () => {
|
||||||
|
it("should show button to view scripts", () => {
|
||||||
|
render(<Page />);
|
||||||
|
expect(screen.getByRole("button", { name: "View Scripts" })).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { describe, it, assert, beforeAll } from "vitest";
|
||||||
|
import { promises as fs } from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import { ScriptSchema, type Script } from "@/app/json-editor/_schemas/schemas";
|
||||||
|
import { Metadata } from "@/lib/types";
|
||||||
|
|
||||||
|
const jsonDir = "public/json";
|
||||||
|
const metadataFileName = "metadata.json";
|
||||||
|
const encoding = "utf-8";
|
||||||
|
|
||||||
|
const fileNames = (await fs.readdir(jsonDir))
|
||||||
|
.filter((fileName) => fileName !== metadataFileName)
|
||||||
|
|
||||||
|
describe.each(fileNames)("%s", async (fileName) => {
|
||||||
|
let script: Script;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const filePath = path.resolve(jsonDir, fileName);
|
||||||
|
const fileContent = await fs.readFile(filePath, encoding)
|
||||||
|
script = JSON.parse(fileContent);
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should have valid json according to script schema", () => {
|
||||||
|
ScriptSchema.parse(script);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have a corresponding script file", () => {
|
||||||
|
script.install_methods.forEach((method) => {
|
||||||
|
const scriptPath = path.resolve("..", method.script)
|
||||||
|
assert(fs.stat(scriptPath), `Script file not found: ${scriptPath}`)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe(`${metadataFileName}`, async () => {
|
||||||
|
let metadata: Metadata;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const filePath = path.resolve(jsonDir, metadataFileName);
|
||||||
|
const fileContent = await fs.readFile(filePath, encoding)
|
||||||
|
metadata = JSON.parse(fileContent);
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should have valid json according to metadata schema", () => {
|
||||||
|
// TODO: create zod schema for metadata. Move zod schemas to /lib/types.ts
|
||||||
|
assert(metadata.categories.length > 0);
|
||||||
|
metadata.categories.forEach((category) => {
|
||||||
|
assert.isString(category.name)
|
||||||
|
assert.isNumber(category.id)
|
||||||
|
assert.isNumber(category.sort_order)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
|
// Mock canvas getContext
|
||||||
|
HTMLCanvasElement.prototype.getContext = vi.fn();
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { Metadata, Script } from "@/lib/types";
|
||||||
|
import { promises as fs } from "fs";
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export const dynamic = "force-static";
|
||||||
|
|
||||||
|
const jsonDir = "public/json";
|
||||||
|
const metadataFileName = "metadata.json";
|
||||||
|
const encoding = "utf-8";
|
||||||
|
|
||||||
|
const getMetadata = async () => {
|
||||||
|
const filePath = path.resolve(jsonDir, metadataFileName);
|
||||||
|
const fileContent = await fs.readFile(filePath, encoding);
|
||||||
|
const metadata: Metadata = JSON.parse(fileContent);
|
||||||
|
return metadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getScripts = async () => {
|
||||||
|
const filePaths = (await fs.readdir(jsonDir))
|
||||||
|
.filter((fileName) => fileName !== metadataFileName)
|
||||||
|
.map((fileName) => path.resolve(jsonDir, fileName));
|
||||||
|
|
||||||
|
const scripts = await Promise.all(
|
||||||
|
filePaths.map(async (filePath) => {
|
||||||
|
const fileContent = await fs.readFile(filePath, encoding);
|
||||||
|
const script: Script = JSON.parse(fileContent);
|
||||||
|
return script;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return scripts;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const metadata = await getMetadata();
|
||||||
|
const scripts = await getScripts();
|
||||||
|
|
||||||
|
const categories = metadata.categories
|
||||||
|
.map((category) => {
|
||||||
|
category.scripts = scripts.filter((script) =>
|
||||||
|
script.categories.includes(category.id),
|
||||||
|
);
|
||||||
|
return category;
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.sort_order - b.sort_order);
|
||||||
|
|
||||||
|
return NextResponse.json(categories);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error as Error);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to fetch categories" },
|
||||||
|
{ status: 500 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,117 @@
|
|||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Category } from "@/lib/types";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { type Script } from "../_schemas/schemas";
|
||||||
|
import { memo } from "react";
|
||||||
|
|
||||||
|
type CategoryProps = {
|
||||||
|
script: Script;
|
||||||
|
setScript: (script: Script) => void;
|
||||||
|
setIsValid: (isValid: boolean) => void;
|
||||||
|
setZodErrors: (zodErrors: z.ZodError | null) => void;
|
||||||
|
categories: Category[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const CategoryTag = memo(({
|
||||||
|
category,
|
||||||
|
onRemove
|
||||||
|
}: {
|
||||||
|
category: Category;
|
||||||
|
onRemove: () => void;
|
||||||
|
}) => (
|
||||||
|
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
|
||||||
|
{category.name}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="ml-1 inline-flex text-blue-400 hover:text-blue-600"
|
||||||
|
onClick={onRemove}
|
||||||
|
>
|
||||||
|
<span className="sr-only">Remove</span>
|
||||||
|
<svg
|
||||||
|
className="h-3 w-3"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth={2}
|
||||||
|
d="M6 18L18 6M6 6l12 12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
|
||||||
|
CategoryTag.displayName = 'CategoryTag';
|
||||||
|
|
||||||
|
function Categories({
|
||||||
|
script,
|
||||||
|
setScript,
|
||||||
|
categories,
|
||||||
|
}: Omit<CategoryProps, "setIsValid" | "setZodErrors">) {
|
||||||
|
const addCategory = (categoryId: number) => {
|
||||||
|
setScript({
|
||||||
|
...script,
|
||||||
|
categories: [...new Set([...script.categories, categoryId])],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeCategory = (categoryId: number) => {
|
||||||
|
setScript({
|
||||||
|
...script,
|
||||||
|
categories: script.categories.filter((id: number) => id !== categoryId),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const categoryMap = new Map(categories.map(c => [c.id, c]));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Label>
|
||||||
|
Category <span className="text-red-500">*</span>
|
||||||
|
</Label>
|
||||||
|
<Select onValueChange={(value) => addCategory(Number(value))}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select a category" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{categories.map((category) => (
|
||||||
|
<SelectItem key={category.id} value={category.id.toString()}>
|
||||||
|
{category.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-wrap gap-2",
|
||||||
|
script.categories.length !== 0 && "mt-2",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{script.categories.map((categoryId) => {
|
||||||
|
const category = categoryMap.get(categoryId);
|
||||||
|
return category ? (
|
||||||
|
<CategoryTag
|
||||||
|
key={categoryId}
|
||||||
|
category={category}
|
||||||
|
onRemove={() => removeCategory(categoryId)}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Categories);
|
||||||
@@ -0,0 +1,240 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { OperatingSystems } from "@/config/siteConfig";
|
||||||
|
import { PlusCircle, Trash2 } from "lucide-react";
|
||||||
|
import { memo, useCallback, useRef } from "react";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { InstallMethodSchema, ScriptSchema, type Script } from "../_schemas/schemas";
|
||||||
|
|
||||||
|
type InstallMethodProps = {
|
||||||
|
script: Script;
|
||||||
|
setScript: (value: Script | ((prevState: Script) => Script)) => void;
|
||||||
|
setIsValid: (isValid: boolean) => void;
|
||||||
|
setZodErrors: (zodErrors: z.ZodError | null) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function InstallMethod({
|
||||||
|
script,
|
||||||
|
setScript,
|
||||||
|
setIsValid,
|
||||||
|
setZodErrors,
|
||||||
|
}: InstallMethodProps) {
|
||||||
|
const cpuRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||||
|
const ramRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||||
|
const hddRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||||
|
|
||||||
|
const addInstallMethod = useCallback(() => {
|
||||||
|
setScript((prev) => {
|
||||||
|
const method = InstallMethodSchema.parse({
|
||||||
|
type: "default",
|
||||||
|
script: `${prev.type}/${prev.slug}.sh`,
|
||||||
|
resources: {
|
||||||
|
cpu: null,
|
||||||
|
ram: null,
|
||||||
|
hdd: null,
|
||||||
|
os: null,
|
||||||
|
version: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
install_methods: [...prev.install_methods, method],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, [setScript]);
|
||||||
|
|
||||||
|
const updateInstallMethod = useCallback(
|
||||||
|
(
|
||||||
|
index: number,
|
||||||
|
key: keyof Script["install_methods"][number],
|
||||||
|
value: Script["install_methods"][number][keyof Script["install_methods"][number]],
|
||||||
|
) => {
|
||||||
|
setScript((prev) => {
|
||||||
|
const updatedMethods = prev.install_methods.map((method, i) => {
|
||||||
|
if (i === index) {
|
||||||
|
const updatedMethod = { ...method, [key]: value };
|
||||||
|
|
||||||
|
if (key === "type") {
|
||||||
|
updatedMethod.script =
|
||||||
|
value === "alpine"
|
||||||
|
? `/${prev.type}/alpine-${prev.slug}.sh`
|
||||||
|
: `/${prev.type}/${prev.slug}.sh`;
|
||||||
|
|
||||||
|
// Set OS to Alpine and reset version if type is alpine
|
||||||
|
if (value === "alpine") {
|
||||||
|
updatedMethod.resources.os = "Alpine";
|
||||||
|
updatedMethod.resources.version = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedMethod;
|
||||||
|
}
|
||||||
|
return method;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updated = {
|
||||||
|
...prev,
|
||||||
|
install_methods: updatedMethods,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = ScriptSchema.safeParse(updated);
|
||||||
|
setIsValid(result.success);
|
||||||
|
if (!result.success) {
|
||||||
|
setZodErrors(result.error);
|
||||||
|
} else {
|
||||||
|
setZodErrors(null);
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[setScript, setIsValid, setZodErrors],
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeInstallMethod = useCallback(
|
||||||
|
(index: number) => {
|
||||||
|
setScript((prev) => ({
|
||||||
|
...prev,
|
||||||
|
install_methods: prev.install_methods.filter((_, i) => i !== index),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
[setScript],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3 className="text-xl font-semibold">Install Methods</h3>
|
||||||
|
{script.install_methods.map((method, index) => (
|
||||||
|
<div key={index} className="space-y-2 border p-4 rounded">
|
||||||
|
<Select
|
||||||
|
value={method.type}
|
||||||
|
onValueChange={(value) => updateInstallMethod(index, "type", value)}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Type" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="default">Default</SelectItem>
|
||||||
|
<SelectItem value="alpine">Alpine</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Input
|
||||||
|
ref={(el) => {
|
||||||
|
cpuRefs.current[index] = el;
|
||||||
|
}}
|
||||||
|
placeholder="CPU in Cores"
|
||||||
|
type="number"
|
||||||
|
value={method.resources.cpu || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateInstallMethod(index, "resources", {
|
||||||
|
...method.resources,
|
||||||
|
cpu: e.target.value ? Number(e.target.value) : null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
ref={(el) => {
|
||||||
|
ramRefs.current[index] = el;
|
||||||
|
}}
|
||||||
|
placeholder="RAM in MB"
|
||||||
|
type="number"
|
||||||
|
value={method.resources.ram || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateInstallMethod(index, "resources", {
|
||||||
|
...method.resources,
|
||||||
|
ram: e.target.value ? Number(e.target.value) : null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
ref={(el) => {
|
||||||
|
hddRefs.current[index] = el;
|
||||||
|
}}
|
||||||
|
placeholder="HDD in GB"
|
||||||
|
type="number"
|
||||||
|
value={method.resources.hdd || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateInstallMethod(index, "resources", {
|
||||||
|
...method.resources,
|
||||||
|
hdd: e.target.value ? Number(e.target.value) : null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Select
|
||||||
|
value={method.resources.os || undefined}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
updateInstallMethod(index, "resources", {
|
||||||
|
...method.resources,
|
||||||
|
os: value || null,
|
||||||
|
version: null, // Reset version when OS changes
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={method.type === "alpine"}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="OS" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{OperatingSystems.map((os) => (
|
||||||
|
<SelectItem key={os.name} value={os.name}>
|
||||||
|
{os.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Select
|
||||||
|
value={method.resources.version || undefined}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
updateInstallMethod(index, "resources", {
|
||||||
|
...method.resources,
|
||||||
|
version: value || null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={method.type === "alpine"}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Version" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{OperatingSystems.find(
|
||||||
|
(os) => os.name === method.resources.os,
|
||||||
|
)?.versions.map((version) => (
|
||||||
|
<SelectItem key={version.slug} value={version.name}>
|
||||||
|
{version.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
size="sm"
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeInstallMethod(index)}
|
||||||
|
>
|
||||||
|
<Trash2 className="mr-2 h-4 w-4" /> Remove Install Method
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
disabled={script.install_methods.length >= 2}
|
||||||
|
onClick={addInstallMethod}
|
||||||
|
>
|
||||||
|
<PlusCircle className="mr-2 h-4 w-4" /> Add Install Method
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(InstallMethod);
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { AlertColors } from "@/config/siteConfig";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { PlusCircle, Trash2 } from "lucide-react";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { ScriptSchema, type Script } from "../_schemas/schemas";
|
||||||
|
import { memo, useCallback, useRef } from "react";
|
||||||
|
|
||||||
|
type NoteProps = {
|
||||||
|
script: Script;
|
||||||
|
setScript: (script: Script) => void;
|
||||||
|
setIsValid: (isValid: boolean) => void;
|
||||||
|
setZodErrors: (zodErrors: z.ZodError | null) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Note({
|
||||||
|
script,
|
||||||
|
setScript,
|
||||||
|
setIsValid,
|
||||||
|
setZodErrors,
|
||||||
|
}: NoteProps) {
|
||||||
|
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
|
||||||
|
|
||||||
|
const addNote = useCallback(() => {
|
||||||
|
setScript({
|
||||||
|
...script,
|
||||||
|
notes: [...script.notes, { text: "", type: "" }],
|
||||||
|
});
|
||||||
|
}, [script, setScript]);
|
||||||
|
|
||||||
|
const updateNote = useCallback((
|
||||||
|
index: number,
|
||||||
|
key: keyof Script["notes"][number],
|
||||||
|
value: string,
|
||||||
|
) => {
|
||||||
|
const updated: Script = {
|
||||||
|
...script,
|
||||||
|
notes: script.notes.map((note, i) =>
|
||||||
|
i === index ? { ...note, [key]: value } : note,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
const result = ScriptSchema.safeParse(updated);
|
||||||
|
setIsValid(result.success);
|
||||||
|
setZodErrors(result.success ? null : result.error);
|
||||||
|
setScript(updated);
|
||||||
|
// Restore focus after state update
|
||||||
|
if (key === "text") {
|
||||||
|
setTimeout(() => {
|
||||||
|
inputRefs.current[index]?.focus();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}, [script, setScript, setIsValid, setZodErrors]);
|
||||||
|
|
||||||
|
const removeNote = useCallback((index: number) => {
|
||||||
|
setScript({
|
||||||
|
...script,
|
||||||
|
notes: script.notes.filter((_, i) => i !== index),
|
||||||
|
});
|
||||||
|
}, [script, setScript]);
|
||||||
|
|
||||||
|
const NoteItem = memo(
|
||||||
|
({ note, index }: { note: Script["notes"][number]; index: number }) => (
|
||||||
|
<div className="space-y-2 border p-4 rounded">
|
||||||
|
<Input
|
||||||
|
placeholder="Note Text"
|
||||||
|
value={note.text}
|
||||||
|
onChange={(e) => updateNote(index, "text", e.target.value)}
|
||||||
|
ref={(el) => {
|
||||||
|
inputRefs.current[index] = el;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Select
|
||||||
|
value={note.type}
|
||||||
|
onValueChange={(value) => updateNote(index, "type", value)}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="flex-1">
|
||||||
|
<SelectValue placeholder="Type" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{Object.keys(AlertColors).map((type) => (
|
||||||
|
<SelectItem key={type} value={type}>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
{type.charAt(0).toUpperCase() + type.slice(1)}{" "}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"size-4 rounded-full border",
|
||||||
|
AlertColors[type as keyof typeof AlertColors],
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="destructive"
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeNote(index)}
|
||||||
|
>
|
||||||
|
<Trash2 className="mr-2 h-4 w-4" /> Remove Note
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
NoteItem.displayName = 'NoteItem';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3 className="text-xl font-semibold">Notes</h3>
|
||||||
|
{script.notes.map((note, index) => (
|
||||||
|
<NoteItem key={index} note={note} index={index} />
|
||||||
|
))}
|
||||||
|
<Button type="button" size="sm" onClick={addNote}>
|
||||||
|
<PlusCircle className="mr-2 h-4 w-4" /> Add Note
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Note);
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const InstallMethodSchema = z.object({
|
||||||
|
type: z.enum(["default", "alpine"], {
|
||||||
|
errorMap: () => ({ message: "Type must be either 'default' or 'alpine'" })
|
||||||
|
}),
|
||||||
|
script: z.string().min(1, "Script content cannot be empty"),
|
||||||
|
resources: z.object({
|
||||||
|
cpu: z.number().nullable(),
|
||||||
|
ram: z.number().nullable(),
|
||||||
|
hdd: z.number().nullable(),
|
||||||
|
os: z.string().nullable(),
|
||||||
|
version: z.string().nullable(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const NoteSchema = z.object({
|
||||||
|
text: z.string().min(1, "Note text cannot be empty"),
|
||||||
|
type: z.string().min(1, "Note type cannot be empty"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ScriptSchema = z.object({
|
||||||
|
name: z.string().min(1, "Name is required"),
|
||||||
|
slug: z.string().min(1, "Slug is required"),
|
||||||
|
categories: z.array(z.number()),
|
||||||
|
date_created: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").min(1, "Date is required"),
|
||||||
|
type: z.enum(["vm", "ct", "misc", "turnkey"], {
|
||||||
|
errorMap: () => ({ message: "Type must be either 'vm', 'ct', 'misc' or 'turnkey'" })
|
||||||
|
}),
|
||||||
|
updateable: z.boolean(),
|
||||||
|
privileged: z.boolean(),
|
||||||
|
interface_port: z.number().nullable(),
|
||||||
|
documentation: z.string().nullable(),
|
||||||
|
website: z.string().url().nullable(),
|
||||||
|
logo: z.string().url().nullable(),
|
||||||
|
description: z.string().min(1, "Description is required"),
|
||||||
|
install_methods: z.array(InstallMethodSchema).min(1, "At least one install method is required"),
|
||||||
|
default_credentials: z.object({
|
||||||
|
username: z.string().nullable(),
|
||||||
|
password: z.string().nullable(),
|
||||||
|
}),
|
||||||
|
notes: z.array(NoteSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Script = z.infer<typeof ScriptSchema>;
|
||||||
@@ -0,0 +1,335 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from "@/components/ui/popover";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { fetchCategories } from "@/lib/data";
|
||||||
|
import { Category } from "@/lib/types";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import { CalendarIcon, Check, Clipboard } from "lucide-react";
|
||||||
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { z } from "zod";
|
||||||
|
import Categories from "./_components/Categories";
|
||||||
|
import InstallMethod from "./_components/InstallMethod";
|
||||||
|
import Note from "./_components/Note";
|
||||||
|
import { ScriptSchema, type Script } from "./_schemas/schemas";
|
||||||
|
|
||||||
|
const initialScript: Script = {
|
||||||
|
name: "",
|
||||||
|
slug: "",
|
||||||
|
categories: [],
|
||||||
|
date_created: "",
|
||||||
|
type: "ct",
|
||||||
|
updateable: false,
|
||||||
|
privileged: false,
|
||||||
|
interface_port: null,
|
||||||
|
documentation: null,
|
||||||
|
website: null,
|
||||||
|
logo: null,
|
||||||
|
description: "",
|
||||||
|
install_methods: [],
|
||||||
|
default_credentials: {
|
||||||
|
username: null,
|
||||||
|
password: null,
|
||||||
|
},
|
||||||
|
notes: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function JSONGenerator() {
|
||||||
|
const [script, setScript] = useState<Script>(initialScript);
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
const [isValid, setIsValid] = useState(false);
|
||||||
|
const [categories, setCategories] = useState<Category[]>([]);
|
||||||
|
const [zodErrors, setZodErrors] = useState<z.ZodError | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories()
|
||||||
|
.then(setCategories)
|
||||||
|
.catch((error) => console.error("Error fetching categories:", error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const updateScript = useCallback(
|
||||||
|
(key: keyof Script, value: Script[keyof Script]) => {
|
||||||
|
setScript((prev) => {
|
||||||
|
const updated = { ...prev, [key]: value };
|
||||||
|
|
||||||
|
if (key === "type" || key === "slug") {
|
||||||
|
updated.install_methods = updated.install_methods.map((method) => ({
|
||||||
|
...method,
|
||||||
|
script:
|
||||||
|
method.type === "alpine"
|
||||||
|
? `/${updated.type}/alpine-${updated.slug}.sh`
|
||||||
|
: `/${updated.type}/${updated.slug}.sh`,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = ScriptSchema.safeParse(updated);
|
||||||
|
setIsValid(result.success);
|
||||||
|
setZodErrors(result.success ? null : result.error);
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleCopy = useCallback(() => {
|
||||||
|
navigator.clipboard.writeText(JSON.stringify(script, null, 2));
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => setIsCopied(false), 2000);
|
||||||
|
toast.success("Copied metadata to clipboard");
|
||||||
|
}, [script]);
|
||||||
|
|
||||||
|
const handleDateSelect = useCallback(
|
||||||
|
(date: Date | undefined) => {
|
||||||
|
updateScript("date_created", format(date || new Date(), "yyyy-MM-dd"));
|
||||||
|
},
|
||||||
|
[updateScript],
|
||||||
|
);
|
||||||
|
|
||||||
|
const formattedDate = useMemo(
|
||||||
|
() =>
|
||||||
|
script.date_created ? format(script.date_created, "PPP") : undefined,
|
||||||
|
[script.date_created],
|
||||||
|
);
|
||||||
|
|
||||||
|
const validationAlert = useMemo(
|
||||||
|
() => (
|
||||||
|
<Alert
|
||||||
|
className={cn("text-black", isValid ? "bg-green-100" : "bg-red-100")}
|
||||||
|
>
|
||||||
|
<AlertTitle>{isValid ? "Valid JSON" : "Invalid JSON"}</AlertTitle>
|
||||||
|
<AlertDescription>
|
||||||
|
{isValid
|
||||||
|
? "The current JSON is valid according to the schema."
|
||||||
|
: "The current JSON does not match the required schema."}
|
||||||
|
</AlertDescription>
|
||||||
|
{zodErrors && (
|
||||||
|
<div className="mt-2 space-y-1">
|
||||||
|
{zodErrors.errors.map((error, index) => (
|
||||||
|
<AlertDescription key={index} className="p-1 text-red-500">
|
||||||
|
{error.path.join(".")} - {error.message}
|
||||||
|
</AlertDescription>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Alert>
|
||||||
|
),
|
||||||
|
[isValid, zodErrors],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-screen mt-20">
|
||||||
|
<div className="w-1/2 p-4 overflow-y-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-4">JSON Generator</h2>
|
||||||
|
<form className="space-y-4">
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<Label>
|
||||||
|
Name <span className="text-red-500">*</span>
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="Example"
|
||||||
|
value={script.name}
|
||||||
|
onChange={(e) => updateScript("name", e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>
|
||||||
|
Slug <span className="text-red-500">*</span>
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="example"
|
||||||
|
value={script.slug}
|
||||||
|
onChange={(e) => updateScript("slug", e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>
|
||||||
|
Logo <span className="text-red-500">*</span>
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
placeholder="Full logo URL"
|
||||||
|
value={script.logo || ""}
|
||||||
|
onChange={(e) => updateScript("logo", e.target.value || null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>
|
||||||
|
Description <span className="text-red-500">*</span>
|
||||||
|
</Label>
|
||||||
|
<Textarea
|
||||||
|
placeholder="Example"
|
||||||
|
value={script.description}
|
||||||
|
onChange={(e) => updateScript("description", e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Categories
|
||||||
|
script={script}
|
||||||
|
setScript={setScript}
|
||||||
|
categories={categories}
|
||||||
|
/>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<Label>Date Created</Label>
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger asChild className="flex-1">
|
||||||
|
<Button
|
||||||
|
variant={"outline"}
|
||||||
|
className={cn(
|
||||||
|
"pl-3 text-left font-normal w-full",
|
||||||
|
!script.date_created && "text-muted-foreground",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{formattedDate || <span>Pick a date</span>}
|
||||||
|
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="w-auto p-0" align="start">
|
||||||
|
<Calendar
|
||||||
|
mode="single"
|
||||||
|
selected={new Date(script.date_created)}
|
||||||
|
onSelect={handleDateSelect}
|
||||||
|
initialFocus
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<Label>Type</Label>
|
||||||
|
<Select
|
||||||
|
value={script.type}
|
||||||
|
onValueChange={(value) => updateScript("type", value)}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="flex-1">
|
||||||
|
<SelectValue placeholder="Type" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="ct">LXC Container</SelectItem>
|
||||||
|
<SelectItem value="vm">Virtual Machine</SelectItem>
|
||||||
|
<SelectItem value="misc">Miscellaneous</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="w-full flex gap-5">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Switch
|
||||||
|
checked={script.updateable}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
updateScript("updateable", checked)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label>Updateable</label>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Switch
|
||||||
|
checked={script.privileged}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
updateScript("privileged", checked)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<label>Privileged</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
placeholder="Interface Port"
|
||||||
|
type="number"
|
||||||
|
value={script.interface_port || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateScript(
|
||||||
|
"interface_port",
|
||||||
|
e.target.value ? Number(e.target.value) : null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Input
|
||||||
|
placeholder="Website URL"
|
||||||
|
value={script.website || ""}
|
||||||
|
onChange={(e) => updateScript("website", e.target.value || null)}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
placeholder="Documentation URL"
|
||||||
|
value={script.documentation || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateScript("documentation", e.target.value || null)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<InstallMethod
|
||||||
|
script={script}
|
||||||
|
setScript={setScript}
|
||||||
|
setIsValid={setIsValid}
|
||||||
|
setZodErrors={setZodErrors}
|
||||||
|
/>
|
||||||
|
<h3 className="text-xl font-semibold">Default Credentials</h3>
|
||||||
|
<Input
|
||||||
|
placeholder="Username"
|
||||||
|
value={script.default_credentials.username || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateScript("default_credentials", {
|
||||||
|
...script.default_credentials,
|
||||||
|
username: e.target.value || null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
placeholder="Password"
|
||||||
|
value={script.default_credentials.password || ""}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateScript("default_credentials", {
|
||||||
|
...script.default_credentials,
|
||||||
|
password: e.target.value || null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Note
|
||||||
|
script={script}
|
||||||
|
setScript={setScript}
|
||||||
|
setIsValid={setIsValid}
|
||||||
|
setZodErrors={setZodErrors}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2 p-4 bg-background overflow-y-auto">
|
||||||
|
{validationAlert}
|
||||||
|
<div className="relative">
|
||||||
|
<Button
|
||||||
|
className="absolute right-2 top-2"
|
||||||
|
size="icon"
|
||||||
|
variant="outline"
|
||||||
|
onClick={handleCopy}
|
||||||
|
>
|
||||||
|
{isCopied ? (
|
||||||
|
<Check className="h-4 w-4" />
|
||||||
|
) : (
|
||||||
|
<Clipboard className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<pre className="mt-4 p-4 bg-secondary rounded shadow overflow-x-scroll">
|
||||||
|
{JSON.stringify(script, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import Footer from "@/components/Footer";
|
||||||
|
import Navbar from "@/components/Navbar";
|
||||||
|
import { ThemeProvider } from "@/components/theme-provider";
|
||||||
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
import { analytics, basePath } from "@/config/siteConfig";
|
||||||
|
import "@/styles/globals.css";
|
||||||
|
import { Inter } from "next/font/google";
|
||||||
|
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
|
export const metadata = {
|
||||||
|
title: "Proxmox VE Helper-Scripts",
|
||||||
|
generator: "Next.js",
|
||||||
|
applicationName: "Proxmox VE Helper-Scripts",
|
||||||
|
referrer: "origin-when-cross-origin",
|
||||||
|
keywords: [
|
||||||
|
"Proxmox VE",
|
||||||
|
"Helper-Scripts",
|
||||||
|
"tteck",
|
||||||
|
"helper",
|
||||||
|
"scripts",
|
||||||
|
"proxmox",
|
||||||
|
"VE",
|
||||||
|
],
|
||||||
|
authors: { name: "Bram Suurd" },
|
||||||
|
creator: "Bram Suurd",
|
||||||
|
publisher: "Bram Suurd",
|
||||||
|
description:
|
||||||
|
"A Front-end for the Proxmox VE Helper-Scripts (Community) Repository. Featuring over 200+ scripts to help you manage your Proxmox VE environment.",
|
||||||
|
favicon: "/app/favicon.ico",
|
||||||
|
formatDetection: {
|
||||||
|
email: false,
|
||||||
|
address: false,
|
||||||
|
telephone: false,
|
||||||
|
},
|
||||||
|
metadataBase: new URL(`https://community-scripts.github.io/${basePath}/`),
|
||||||
|
openGraph: {
|
||||||
|
title: "Proxmox VE Helper-Scripts",
|
||||||
|
description:
|
||||||
|
"A Front-end for the Proxmox VE Helper-Scripts (Community) Repository. Featuring over 200+ scripts to help you manage your Proxmox VE environment.",
|
||||||
|
url: "/defaultimg.png",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: `https://community-scripts.github.io/${basePath}/defaultimg.png`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
locale: "en_US",
|
||||||
|
type: "website",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
}>) {
|
||||||
|
return (
|
||||||
|
<html lang="en" suppressHydrationWarning>
|
||||||
|
<head>
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
src={`https://${analytics.url}/script.js`}
|
||||||
|
data-website-id={analytics.token}
|
||||||
|
></script>
|
||||||
|
<link rel="canonical" href={metadata.metadataBase.href} />
|
||||||
|
<link rel="manifest" href="manifest.webmanifest" />
|
||||||
|
<link rel="preconnect" href="https://api.github.com" />
|
||||||
|
</head>
|
||||||
|
<body className={inter.className}>
|
||||||
|
<ThemeProvider
|
||||||
|
attribute="class"
|
||||||
|
defaultTheme="dark"
|
||||||
|
enableSystem
|
||||||
|
disableTransitionOnChange
|
||||||
|
>
|
||||||
|
<div className="flex w-full flex-col justify-center">
|
||||||
|
<Navbar />
|
||||||
|
<div className="flex min-h-screen flex-col justify-center">
|
||||||
|
<div className="flex w-full justify-center">
|
||||||
|
<div className="w-full max-w-7xl ">
|
||||||
|
<NuqsAdapter>{children}</NuqsAdapter>
|
||||||
|
<Toaster richColors />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export const generateStaticParams = () => {
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function manifest(): MetadataRoute.Manifest {
|
||||||
|
return {
|
||||||
|
name: "Proxmox VE Helper-Scripts",
|
||||||
|
short_name: "Proxmox VE Helper-Scripts",
|
||||||
|
description:
|
||||||
|
"A Re-designed Front-end for the Proxmox VE Helper-Scripts Repository. Featuring over 200+ scripts to help you manage your Proxmox VE environment.",
|
||||||
|
theme_color: "#030712",
|
||||||
|
background_color: "#030712",
|
||||||
|
display: "standalone",
|
||||||
|
orientation: "portrait",
|
||||||
|
scope: `${basePath}`,
|
||||||
|
start_url: `${basePath}`,
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: "logo.png",
|
||||||
|
sizes: "512x512",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
"use client";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
export default function NotFoundPage() {
|
||||||
|
return (
|
||||||
|
<div className="flex h-screen w-full flex-col items-center justify-center gap-5 bg-background px-4 md:px-6">
|
||||||
|
<div className="space-y-2 text-center">
|
||||||
|
<h1 className="text-4xl font-bold tracking-tighter sm:text-5xl md:text-6xl">
|
||||||
|
404
|
||||||
|
</h1>
|
||||||
|
<p className="text-muted-foreground md:text-xl">
|
||||||
|
Oops, the page you are looking for could not be found.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button onClick={() => window.history.back()} variant="secondary">
|
||||||
|
Go Back
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
"use client";
|
||||||
|
import AnimatedGradientText from "@/components/ui/animated-gradient-text";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { CardFooter } from "@/components/ui/card";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import Particles from "@/components/ui/particles";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { ArrowRightIcon, ExternalLink } from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { FaGithub } from "react-icons/fa";
|
||||||
|
|
||||||
|
function CustomArrowRightIcon() {
|
||||||
|
return <ArrowRightIcon className="h-4 w-4" width={1} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const { theme } = useTheme();
|
||||||
|
|
||||||
|
const [color, setColor] = useState("#000000");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setColor(theme === "dark" ? "#ffffff" : "#000000");
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full mt-16">
|
||||||
|
<Particles
|
||||||
|
className="absolute inset-0 -z-40"
|
||||||
|
quantity={100}
|
||||||
|
ease={80}
|
||||||
|
color={color}
|
||||||
|
refresh
|
||||||
|
/>
|
||||||
|
<div className="container mx-auto">
|
||||||
|
<div className="flex h-[80vh] flex-col items-center justify-center gap-4 py-20 lg:py-40">
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger>
|
||||||
|
<div>
|
||||||
|
<AnimatedGradientText>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
`absolute inset-0 block size-full animate-gradient bg-gradient-to-r from-[#ffaa40]/50 via-[#9c40ff]/50 to-[#ffaa40]/50 bg-[length:var(--bg-size)_100%] [border-radius:inherit] [mask:linear-gradient(#fff_0_0)_content-box,linear-gradient(#fff_0_0)]`,
|
||||||
|
`p-px ![mask-composite:subtract]`,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
❤️ <Separator className="mx-2 h-4" orientation="vertical" />
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
`animate-gradient bg-gradient-to-r from-[#ffaa40] via-[#9c40ff] to-[#ffaa40] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent`,
|
||||||
|
`inline`,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Scripts by Tteck
|
||||||
|
</span>
|
||||||
|
</AnimatedGradientText>
|
||||||
|
</div>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Thank You!</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
A big thank you to Tteck and the many contributors who have
|
||||||
|
made this project possible. Your hard work is truly
|
||||||
|
appreciated by the entire Proxmox community!
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<CardFooter className="flex flex-col gap-2">
|
||||||
|
<Button className="w-full" variant="outline" asChild>
|
||||||
|
<a
|
||||||
|
href="https://github.com/tteck"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<FaGithub className="mr-2 h-4 w-4" /> Tteck's GitHub
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
<Button className="w-full" asChild>
|
||||||
|
<a
|
||||||
|
href={`https://github.com/community-scripts/${basePath}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-center"
|
||||||
|
>
|
||||||
|
<ExternalLink className="mr-2 h-4 w-4" /> Proxmox Helper
|
||||||
|
Scripts
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<h1 className="max-w-2xl text-center text-5xl font-semibold tracking-tighter md:text-7xl">
|
||||||
|
Make managing your Homelab a breeze
|
||||||
|
</h1>
|
||||||
|
<p className="max-w-2xl text-center text-lg leading-relaxed tracking-tight text-muted-foreground md:text-xl">
|
||||||
|
We are a community-driven initiative that simplifies the setup of
|
||||||
|
Proxmox Virtual Environment (VE).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Originally created by{" "}
|
||||||
|
<a href="https://github.com/tteck" target="_blank">
|
||||||
|
tteck
|
||||||
|
</a>
|
||||||
|
, these scripts automate and streamline
|
||||||
|
<br />
|
||||||
|
the process of creating and configuring Linux containers (LXC) and
|
||||||
|
virtual machines (VMs) on Proxmox VE.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
With 200+ scripts to help you manage your{" "}
|
||||||
|
<b>Proxmox VE environment</b>.<br />
|
||||||
|
Whether you're a seasoned user or a newcomer, we've got
|
||||||
|
you covered.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row gap-3">
|
||||||
|
<Link href="/scripts">
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
variant="expandIcon"
|
||||||
|
Icon={CustomArrowRightIcon}
|
||||||
|
iconPlacement="right"
|
||||||
|
className="hover:"
|
||||||
|
>
|
||||||
|
View Scripts
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
import type { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export const dynamic = "force-static";
|
||||||
|
|
||||||
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: "*",
|
||||||
|
allow: "/",
|
||||||
|
},
|
||||||
|
sitemap: `https://community-scripts.github.io/${basePath}/sitemap.xml`,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
import { formattedBadge } from "@/components/CommandMenu";
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionContent,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionTrigger,
|
||||||
|
} from "@/components/ui/accordion";
|
||||||
|
import { Category } from "@/lib/types";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
|
||||||
|
export default function ScriptAccordion({
|
||||||
|
items,
|
||||||
|
selectedScript,
|
||||||
|
setSelectedScript,
|
||||||
|
}: {
|
||||||
|
items: Category[];
|
||||||
|
selectedScript: string | null;
|
||||||
|
setSelectedScript: (script: string | null) => void;
|
||||||
|
}) {
|
||||||
|
const [expandedItem, setExpandedItem] = useState<string | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({});
|
||||||
|
|
||||||
|
const handleAccordionChange = (value: string | undefined) => {
|
||||||
|
setExpandedItem(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelected = useCallback(
|
||||||
|
(slug: string) => {
|
||||||
|
setSelectedScript(slug);
|
||||||
|
},
|
||||||
|
[setSelectedScript],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedScript) {
|
||||||
|
const category = items.find((category) =>
|
||||||
|
category.scripts.some((script) => script.slug === selectedScript),
|
||||||
|
);
|
||||||
|
if (category) {
|
||||||
|
setExpandedItem(category.name);
|
||||||
|
handleSelected(selectedScript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedScript, items, handleSelected]);
|
||||||
|
return (
|
||||||
|
<Accordion
|
||||||
|
type="single"
|
||||||
|
value={expandedItem}
|
||||||
|
onValueChange={handleAccordionChange}
|
||||||
|
collapsible
|
||||||
|
className="overflow-y-scroll max-h-[calc(100vh-220px)] overflow-x-hidden mt-3 p-2"
|
||||||
|
>
|
||||||
|
{items.map((category) => (
|
||||||
|
<AccordionItem
|
||||||
|
key={category.id + ":category"}
|
||||||
|
value={category.name}
|
||||||
|
className={cn("sm:text-md flex flex-col border-none", {
|
||||||
|
"rounded-lg bg-accent/30": expandedItem === category.name,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<AccordionTrigger
|
||||||
|
className={cn(
|
||||||
|
"duration-250 rounded-lg transition ease-in-out hover:-translate-y-1 hover:scale-105 hover:bg-accent",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="mr-2 flex w-full items-center justify-between">
|
||||||
|
<span className="pl-2">{category.name} </span>
|
||||||
|
<span className="rounded-full bg-gray-200 px-2 py-1 text-xs text-muted-foreground hover:no-underline dark:bg-blue-800/20">
|
||||||
|
{category.scripts.length}
|
||||||
|
</span>
|
||||||
|
</div>{" "}
|
||||||
|
</AccordionTrigger>
|
||||||
|
<AccordionContent
|
||||||
|
data-state={expandedItem === category.name ? "open" : "closed"}
|
||||||
|
className="pt-0"
|
||||||
|
>
|
||||||
|
{category.scripts
|
||||||
|
.slice()
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
.map((script, index) => (
|
||||||
|
<div key={index}>
|
||||||
|
<Link
|
||||||
|
href={{
|
||||||
|
pathname: "/scripts",
|
||||||
|
query: { id: script.slug },
|
||||||
|
}}
|
||||||
|
prefetch={false}
|
||||||
|
className={`flex cursor-pointer items-center justify-between gap-1 px-1 py-1 text-muted-foreground hover:rounded-lg hover:bg-accent/60 hover:dark:bg-accent/20 ${
|
||||||
|
selectedScript === script.slug
|
||||||
|
? "rounded-lg bg-accent font-semibold dark:bg-accent/30 dark:text-white"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
onClick={() => handleSelected(script.slug)}
|
||||||
|
ref={(el) => {
|
||||||
|
linkRefs.current[script.slug] = el;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Image
|
||||||
|
src={script.logo || `/${basePath}/logo.png`}
|
||||||
|
height={16}
|
||||||
|
width={16}
|
||||||
|
unoptimized
|
||||||
|
onError={(e) =>
|
||||||
|
((e.currentTarget as HTMLImageElement).src =
|
||||||
|
`/${basePath}/logo.png`)
|
||||||
|
}
|
||||||
|
alt={script.name}
|
||||||
|
className="mr-1 w-4 h-4 rounded-full"
|
||||||
|
/>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
{script.name}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{formattedBadge(script.type)}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
))}
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { basePath, mostPopularScripts } from "@/config/siteConfig";
|
||||||
|
import { extractDate } from "@/lib/time";
|
||||||
|
import { Category, Script } from "@/lib/types";
|
||||||
|
import { CalendarPlus } from "lucide-react";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
|
||||||
|
const ITEMS_PER_PAGE = 3;
|
||||||
|
|
||||||
|
export const getDisplayValueFromType = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "ct":
|
||||||
|
return "LXC";
|
||||||
|
case "vm":
|
||||||
|
return "VM";
|
||||||
|
case "misc":
|
||||||
|
return "";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function LatestScripts({ items }: { items: Category[] }) {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
|
const latestScripts = useMemo(() => {
|
||||||
|
if (!items) return [];
|
||||||
|
const scripts = items.flatMap((category) => category.scripts || []);
|
||||||
|
return scripts.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.date_created).getTime() - new Date(a.date_created).getTime(),
|
||||||
|
);
|
||||||
|
}, [items]);
|
||||||
|
|
||||||
|
const goToNextPage = () => {
|
||||||
|
setPage((prevPage) => prevPage + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToPreviousPage = () => {
|
||||||
|
setPage((prevPage) => prevPage - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
||||||
|
const endIndex = page * ITEMS_PER_PAGE;
|
||||||
|
|
||||||
|
if (!items) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
{latestScripts.length > 0 && (
|
||||||
|
<div className="flex w-full items-center justify-between">
|
||||||
|
<h2 className="text-lg font-semibold">Newest Scripts</h2>
|
||||||
|
<div className="flex items-center justify-end gap-1">
|
||||||
|
{page > 1 && (
|
||||||
|
<div
|
||||||
|
className="cursor-pointer select-none p-2 text-sm font-semibold"
|
||||||
|
onClick={goToPreviousPage}
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{endIndex < latestScripts.length && (
|
||||||
|
<div
|
||||||
|
onClick={goToNextPage}
|
||||||
|
className="cursor-pointer select-none p-2 text-sm font-semibold"
|
||||||
|
>
|
||||||
|
{page === 1 ? "More.." : "Next"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||||
|
{latestScripts.slice(startIndex, endIndex).map((script) => (
|
||||||
|
<Card
|
||||||
|
key={script.slug}
|
||||||
|
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||||
|
>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-3">
|
||||||
|
<div className="flex h-16 w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||||
|
<Image
|
||||||
|
src={script.logo || `/${basePath}/logo.png`}
|
||||||
|
unoptimized
|
||||||
|
height={64}
|
||||||
|
width={64}
|
||||||
|
alt=""
|
||||||
|
onError={(e) =>
|
||||||
|
((e.currentTarget as HTMLImageElement).src =
|
||||||
|
`/${basePath}/logo.png`)
|
||||||
|
}
|
||||||
|
className="h-11 w-11 object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<p className="text-lg line-clamp-1">
|
||||||
|
{script.name} {getDisplayValueFromType(script.type)}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-muted-foreground flex items-center gap-1">
|
||||||
|
<CalendarPlus className="h-4 w-4" />
|
||||||
|
{extractDate(script.date_created)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<CardDescription className="line-clamp-3 text-card-foreground">
|
||||||
|
{script.description}
|
||||||
|
</CardDescription>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="">
|
||||||
|
<Button asChild variant="outline">
|
||||||
|
<Link
|
||||||
|
href={{
|
||||||
|
pathname: "/scripts",
|
||||||
|
query: { id: script.slug },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View Script
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MostViewedScripts({ items }: { items: Category[] }) {
|
||||||
|
const mostViewedScripts = items.reduce((acc: Script[], category) => {
|
||||||
|
const foundScripts = category.scripts.filter((script) =>
|
||||||
|
mostPopularScripts.includes(script.name),
|
||||||
|
);
|
||||||
|
return acc.concat(foundScripts);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
{mostViewedScripts.length > 0 && (
|
||||||
|
<>
|
||||||
|
<h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||||
|
{mostViewedScripts.map((script) => (
|
||||||
|
<Card
|
||||||
|
key={script.slug}
|
||||||
|
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||||
|
>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle className="flex items-center gap-3">
|
||||||
|
<div className="flex max-h-16 min-h-16 min-w-16 max-w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||||
|
<Image
|
||||||
|
unoptimized
|
||||||
|
src={script.logo || `/${basePath}/logo.png`}
|
||||||
|
height={64}
|
||||||
|
width={64}
|
||||||
|
alt=""
|
||||||
|
onError={(e) =>
|
||||||
|
((e.currentTarget as HTMLImageElement).src =
|
||||||
|
`/${basePath}/logo.png`)
|
||||||
|
}
|
||||||
|
className="h-11 w-11 object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<p className="line-clamp-1 text-lg">
|
||||||
|
{script.name} {getDisplayValueFromType(script.type)}
|
||||||
|
</p>
|
||||||
|
<p className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||||
|
<CalendarPlus className="h-4 w-4" />
|
||||||
|
{extractDate(script.date_created)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<CardDescription className="line-clamp-3 text-card-foreground break-words">
|
||||||
|
{script.description}
|
||||||
|
</CardDescription>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="">
|
||||||
|
<Button asChild variant="outline">
|
||||||
|
<Link
|
||||||
|
href={{
|
||||||
|
pathname: "/scripts",
|
||||||
|
query: { id: script.slug },
|
||||||
|
}}
|
||||||
|
prefetch={false}
|
||||||
|
>
|
||||||
|
View Script
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
"use client";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { extractDate } from "@/lib/time";
|
||||||
|
import { Script } from "@/lib/types";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
import { getDisplayValueFromType } from "./ScriptInfoBlocks";
|
||||||
|
import Alerts from "./ScriptItems/Alerts";
|
||||||
|
import Buttons from "./ScriptItems/Buttons";
|
||||||
|
import DefaultPassword from "./ScriptItems/DefaultPassword";
|
||||||
|
import DefaultSettings from "./ScriptItems/DefaultSettings";
|
||||||
|
import Description from "./ScriptItems/Description";
|
||||||
|
import InstallCommand from "./ScriptItems/InstallCommand";
|
||||||
|
import InterFaces from "./ScriptItems/InterFaces";
|
||||||
|
import Tooltips from "./ScriptItems/Tooltips";
|
||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
|
||||||
|
function ScriptItem({
|
||||||
|
item,
|
||||||
|
setSelectedScript,
|
||||||
|
}: {
|
||||||
|
item: Script;
|
||||||
|
setSelectedScript: (script: string | null) => void;
|
||||||
|
}) {
|
||||||
|
const closeScript = () => {
|
||||||
|
window.history.pushState({}, document.title, window.location.pathname);
|
||||||
|
setSelectedScript(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mr-7 mt-0 flex w-full min-w-fit">
|
||||||
|
<div className="flex w-full min-w-fit">
|
||||||
|
<div className="flex w-full flex-col">
|
||||||
|
<div className="flex h-[36px] min-w-max items-center justify-between">
|
||||||
|
<h2 className="text-lg font-semibold">Selected Script</h2>
|
||||||
|
<X onClick={closeScript} className="cursor-pointer" />
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg border bg-accent/20 p-4">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<div className="flex">
|
||||||
|
<Image
|
||||||
|
className="h-32 w-32 rounded-lg bg-accent/60 object-contain p-3 shadow-md"
|
||||||
|
src={item.logo || `/${basePath}/logo.png`}
|
||||||
|
width={400}
|
||||||
|
onError={(e) =>
|
||||||
|
((e.currentTarget as HTMLImageElement).src =
|
||||||
|
`/${basePath}/logo.png`)
|
||||||
|
}
|
||||||
|
height={400}
|
||||||
|
alt={item.name}
|
||||||
|
unoptimized
|
||||||
|
/>
|
||||||
|
<div className="ml-4 flex flex-col justify-between">
|
||||||
|
<div className="flex h-full w-full flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-lg font-semibold">
|
||||||
|
{item.name} {getDisplayValueFromType(item.type)}
|
||||||
|
</h1>
|
||||||
|
<p className="w-full text-sm text-muted-foreground">
|
||||||
|
Date added: {extractDate(item.date_created)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-5">
|
||||||
|
<DefaultSettings item={item} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hidden flex-col justify-between gap-2 sm:flex">
|
||||||
|
<InterFaces item={item} />
|
||||||
|
<Buttons item={item} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Separator className="mt-4" />
|
||||||
|
<div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<Description item={item} />
|
||||||
|
<Alerts item={item} />
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 rounded-lg border bg-accent/50">
|
||||||
|
<div className="flex gap-3 px-4 py-2">
|
||||||
|
<h2 className="text-lg font-semibold">
|
||||||
|
How to {item.type == "misc" ? "use" : "install"}
|
||||||
|
</h2>
|
||||||
|
<Tooltips item={item} />
|
||||||
|
</div>
|
||||||
|
<Separator className="w-full"></Separator>
|
||||||
|
<InstallCommand item={item} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DefaultPassword item={item} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ScriptItem;
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import TextCopyBlock from "@/components/TextCopyBlock";
|
||||||
|
import { AlertColors } from "@/config/siteConfig";
|
||||||
|
import { Script } from "@/lib/types";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
import { AlertCircle, NotepadText } from "lucide-react";
|
||||||
|
|
||||||
|
type NoteProps = {
|
||||||
|
text: string;
|
||||||
|
type: keyof typeof AlertColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Alerts({ item }: { item: Script }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{item?.notes?.length > 0 &&
|
||||||
|
item.notes.map((note: NoteProps, index: number) => (
|
||||||
|
<div key={index} className="mt-4 flex flex-col gap-2">
|
||||||
|
<p
|
||||||
|
className={cn(
|
||||||
|
"inline-flex items-center gap-2 rounded-lg border p-2 pl-4 text-sm",
|
||||||
|
AlertColors[note.type],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{note.type == "info" ? (
|
||||||
|
<NotepadText className="h-4 min-h-4 w-4 min-w-4" />
|
||||||
|
) : (
|
||||||
|
<AlertCircle className="h-4 min-h-4 w-4 min-w-4" />
|
||||||
|
)}
|
||||||
|
<span>{TextCopyBlock(note.text)}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { basePath } from "@/config/siteConfig";
|
||||||
|
import { Script } from "@/lib/types";
|
||||||
|
import { BookOpenText, Code, Globe } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
const generateSourceUrl = (slug: string, type: string) => {
|
||||||
|
const baseUrl = `https://raw.githubusercontent.com/community-scripts/${basePath}/main`;
|
||||||
|
return type === "ct"
|
||||||
|
? `${baseUrl}/install/${slug}-install.sh`
|
||||||
|
: `${baseUrl}/${type}/${slug}.sh`;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ButtonLinkProps {
|
||||||
|
href: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ButtonLink = ({ href, icon, text }: ButtonLinkProps) => (
|
||||||
|
<Button variant="secondary" asChild>
|
||||||
|
<Link target="_blank" href={href}>
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
{icon}
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function Buttons({ item }: { item: Script }) {
|
||||||
|
const buttons = [
|
||||||
|
item.website && {
|
||||||
|
href: item.website,
|
||||||
|
icon: <Globe className="h-4 w-4" />,
|
||||||
|
text: "Website",
|
||||||
|
},
|
||||||
|
item.documentation && {
|
||||||
|
href: item.documentation,
|
||||||
|
icon: <BookOpenText className="h-4 w-4" />,
|
||||||
|
text: "Documentation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: generateSourceUrl(item.slug, item.type),
|
||||||
|
icon: <Code className="h-4 w-4" />,
|
||||||
|
text: "Source Code",
|
||||||
|
},
|
||||||
|
].filter(Boolean) as ButtonLinkProps[];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-wrap justify-end gap-2">
|
||||||
|
{buttons.map((props, index) => (
|
||||||
|
<ButtonLink key={index} {...props} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import handleCopy from "@/components/handleCopy";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Separator } from "@/components/ui/separator";
|
||||||
|
import { Script } from "@/lib/types";
|
||||||
|
|
||||||
|
export default function DefaultPassword({ item }: { item: Script }) {
|
||||||
|
const { username, password } = item.default_credentials;
|
||||||
|
const hasDefaultLogin = username && password;
|
||||||
|
|
||||||
|
if (!hasDefaultLogin) return null;
|
||||||
|
|
||||||
|
const copyCredential = (type: "username" | "password") => {
|
||||||
|
handleCopy(type, item.default_credentials[type] ?? "");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4 rounded-lg border bg-accent/50">
|
||||||
|
<div className="flex gap-3 px-4 py-2">
|
||||||
|
<h2 className="text-lg font-semibold">Default Login Credentials</h2>
|
||||||
|
</div>
|
||||||
|
<Separator className="w-full" />
|
||||||
|
<div className="flex flex-col gap-2 p-4">
|
||||||
|
<p className="mb-2 text-sm">
|
||||||
|
You can use the following credentials to login to the {item.name}{" "}
|
||||||
|
{item.type}.
|
||||||
|
</p>
|
||||||
|
{["username", "password"].map((type) => (
|
||||||
|
<div key={type} className="text-sm">
|
||||||
|
{type.charAt(0).toUpperCase() + type.slice(1)}:{" "}
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="null"
|
||||||
|
onClick={() => copyCredential(type as "username" | "password")}
|
||||||
|
>
|
||||||
|
{item.default_credentials[type as "username" | "password"]}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { Script } from "@/lib/types";
|
||||||
|
|
||||||
|
export default function DefaultSettings({ item }: { item: Script }) {
|
||||||
|
const getDisplayValueFromRAM = (ram: number) =>
|
||||||
|
ram >= 1024 ? `${Math.floor(ram / 1024)}GB` : `${ram}MB`;
|
||||||
|
|
||||||
|
const ResourceDisplay = ({
|
||||||
|
settings,
|
||||||
|
title,
|
||||||
|
}: {
|
||||||
|
settings: (typeof item.install_methods)[0];
|
||||||
|
title: string;
|
||||||
|
}) => {
|
||||||
|
const { cpu, ram, hdd } = settings.resources;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-md font-semibold">{title}</h2>
|
||||||
|
<p className="text-sm text-muted-foreground">CPU: {cpu}vCPU</p>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
RAM: {getDisplayValueFromRAM(ram ?? 0)}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-muted-foreground">HDD: {hdd}GB</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultSettings = item.install_methods.find(
|
||||||
|
(method) => method.type === "default",
|
||||||
|
);
|
||||||
|
const defaultAlpineSettings = item.install_methods.find(
|
||||||
|
(method) => method.type === "alpine",
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasDefaultSettings =
|
||||||
|
defaultSettings?.resources &&
|
||||||
|
Object.values(defaultSettings.resources).some(Boolean);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{hasDefaultSettings && (
|
||||||
|
<ResourceDisplay settings={defaultSettings} title="Default settings" />
|
||||||
|
)}
|
||||||
|
{defaultAlpineSettings && (
|
||||||
|
<ResourceDisplay
|
||||||
|
settings={defaultAlpineSettings}
|
||||||
|
title="Default Alpine settings"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import TextCopyBlock from "@/components/TextCopyBlock";
|
||||||
|
import { Script } from "@/lib/types";
|
||||||
|
|
||||||
|
export default function Description({ item }: { item: Script }) {
|
||||||
|
return (
|
||||||
|
<div className="p-2">
|
||||||
|
<h2 className="mb-2 max-w-prose text-lg font-semibold">Description</h2>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
{TextCopyBlock(item.description)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user