mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-12-18 05:03:30 +01:00
Compare commits
113 Commits
2025-12-13
...
github-act
| Author | SHA1 | Date | |
|---|---|---|---|
| dde61a2433 | |||
| 5e3eca2832 | |||
| bc479d7ffe | |||
| 610ec3d157 | |||
| 6d26dc2043 | |||
| 6bdeddee37 | |||
| 25baf6c809 | |||
| f42a7becf5 | |||
| acdb3b5908 | |||
| cb13f5de3c | |||
| c4afe3349b | |||
| dcc4b316a9 | |||
| 7a7c9f9a22 | |||
| c1c223ea45 | |||
| b3629b47da | |||
| 82cdcf7bfe | |||
| a823241d96 | |||
| e64c07e44c | |||
| 21f7914294 | |||
| 30056854c9 | |||
| 15a061f976 | |||
| b279888e96 | |||
| c9dd003445 | |||
| 39821677f0 | |||
| 4b3ebfc8ec | |||
| 4f2c707605 | |||
| 360eff6951 | |||
| 3b80730873 | |||
| f9baa783b0 | |||
| 3a9d03fdb7 | |||
| 8e3da31471 | |||
| d058dc515e | |||
| 03a8071ef4 | |||
| 033879f712 | |||
| fc3767d9c1 | |||
| 9135cc3f31 | |||
| 93a4ce5e33 | |||
| 0271dddfd5 | |||
| 5a263b5036 | |||
| 60635feeab | |||
| 7261ffe8a2 | |||
| 44ea7cecb8 | |||
| 5f6af94ca6 | |||
| 059aaac914 | |||
| 951fb3d53a | |||
| 000c8b5fc9 | |||
| baaf6a9f58 | |||
| 4ff31f3dcf | |||
| 0dd4a9e6ed | |||
| 3dc2ea7d50 | |||
| 1333624879 | |||
| c1831f9bc8 | |||
| 4b09cb3d00 | |||
| 01b147d28a | |||
| e95ae11f88 | |||
| f2a2ec30ba | |||
| 798015df6f | |||
| 2773faee08 | |||
| b524cbe232 | |||
| 7b55077a00 | |||
| 7ab0327376 | |||
| 51ba8ca7c8 | |||
| 6d78e4da6b | |||
| a3fb28105d | |||
| cc7eb7fd35 | |||
| b605e463d1 | |||
| 71c2f4e7f8 | |||
| 648ca5e4d0 | |||
| 0917921225 | |||
| c269dc3b13 | |||
| d0a09ccd5d | |||
| 494ab1cee3 | |||
| 568bbb7f32 | |||
| 3026a405c8 | |||
| 7d98f80eb7 | |||
| f4c1b68881 | |||
| a949a1cc97 | |||
| 1e6b9a7001 | |||
| 8672aa075a | |||
| aaa20f7845 | |||
| 6da27a7112 | |||
| 8e07685aab | |||
| 5ba55d1f5a | |||
| 126b0c339a | |||
| c2034039e8 | |||
| 9374e5d183 | |||
| 6311584fef | |||
| 5bbf0861e9 | |||
| 7cb02a0cc3 | |||
| 010e8d5f27 | |||
| 2b322bf182 | |||
| d12215dea8 | |||
| f258ab7ae5 | |||
| 33f167f278 | |||
| 3568cf52f9 | |||
| 5f5144c661 | |||
| 09134d94dd | |||
| 33103ad256 | |||
| fd75da89c4 | |||
| ee49576f3a | |||
| e651c14f76 | |||
| 1fc5c031cc | |||
| 35793051a1 | |||
| 9a6a0379a6 | |||
| 4fab369a5b | |||
| f977f6c987 | |||
| 2524dd1af7 | |||
| dfcaa70647 | |||
| 7b911403a3 | |||
| 1a96ed2221 | |||
| b180694d46 | |||
| f807ec748d | |||
| b9f29f2bd3 |
1
.github/pull_request_template.md
generated
vendored
1
.github/pull_request_template.md
generated
vendored
@ -3,6 +3,7 @@ PRs without prior testing will be closed. -->
|
|||||||
|
|
||||||
## ✍️ Description
|
## ✍️ Description
|
||||||
|
|
||||||
|
|
||||||
## 🔗 Related Issue
|
## 🔗 Related Issue
|
||||||
|
|
||||||
Fixes #
|
Fixes #
|
||||||
|
|||||||
123
CHANGELOG.md
123
CHANGELOG.md
@ -10,8 +10,131 @@
|
|||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
|
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
|
||||||
|
|
||||||
|
## 2025-12-18
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- [HOTFIX] Fix Scanopy release check [@vhsdream](https://github.com/vhsdream) ([#10097](https://github.com/community-scripts/ProxmoxVE/pull/10097))
|
||||||
|
|
||||||
|
## 2025-12-17
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- Tracktor: updated environment variables for latest release [@javedh-dev](https://github.com/javedh-dev) ([#10067](https://github.com/community-scripts/ProxmoxVE/pull/10067))
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Semaphore: Fix release binary package fetching [@tremor021](https://github.com/tremor021) ([#10055](https://github.com/community-scripts/ProxmoxVE/pull/10055))
|
||||||
|
- update github repo for endurain [@johanngrobe](https://github.com/johanngrobe) ([#10074](https://github.com/community-scripts/ProxmoxVE/pull/10074))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- use setup_hwaccel for robust hardware acceleration [@MickLesk](https://github.com/MickLesk) ([#10054](https://github.com/community-scripts/ProxmoxVE/pull/10054))
|
||||||
|
- add hardware acceleration support for 17 additional apps [@MickLesk](https://github.com/MickLesk) ([#10061](https://github.com/community-scripts/ProxmoxVE/pull/10061))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Telegraf: Small refactor [@tremor021](https://github.com/tremor021) ([#10056](https://github.com/community-scripts/ProxmoxVE/pull/10056))
|
||||||
|
- Refactor: Salt [@tremor021](https://github.com/tremor021) ([#10057](https://github.com/community-scripts/ProxmoxVE/pull/10057))
|
||||||
|
- Refactor: Resilio Sync [@tremor021](https://github.com/tremor021) ([#10058](https://github.com/community-scripts/ProxmoxVE/pull/10058))
|
||||||
|
- Refactor: Reitti [@tremor021](https://github.com/tremor021) ([#10059](https://github.com/community-scripts/ProxmoxVE/pull/10059))
|
||||||
|
- Refactor: Redis [@tremor021](https://github.com/tremor021) ([#10060](https://github.com/community-scripts/ProxmoxVE/pull/10060))
|
||||||
|
- Refactor: Reactive-Resume [@tremor021](https://github.com/tremor021) ([#10062](https://github.com/community-scripts/ProxmoxVE/pull/10062))
|
||||||
|
- Refactor: RDTClient [@tremor021](https://github.com/tremor021) ([#10064](https://github.com/community-scripts/ProxmoxVE/pull/10064))
|
||||||
|
- Refactor: RabbitMQ [@tremor021](https://github.com/tremor021) ([#10065](https://github.com/community-scripts/ProxmoxVE/pull/10065))
|
||||||
|
- Qdrant: Code cleanup [@tremor021](https://github.com/tremor021) ([#10066](https://github.com/community-scripts/ProxmoxVE/pull/10066))
|
||||||
|
- Refactor: Pterodactyl Wings [@tremor021](https://github.com/tremor021) ([#10069](https://github.com/community-scripts/ProxmoxVE/pull/10069))
|
||||||
|
|
||||||
|
## 2025-12-16
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- [REFACTOR]: NetVisor => Scanopy [@vhsdream](https://github.com/vhsdream) ([#10011](https://github.com/community-scripts/ProxmoxVE/pull/10011))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- zabbix: fix repo url after change [@MickLesk](https://github.com/MickLesk) ([#10042](https://github.com/community-scripts/ProxmoxVE/pull/10042))
|
||||||
|
- Fix: mariadb repo in update_scripts [@MickLesk](https://github.com/MickLesk) ([#10034](https://github.com/community-scripts/ProxmoxVE/pull/10034))
|
||||||
|
- 2fauth: update PHP version from 8.3 to 8.4 in update_script [@MickLesk](https://github.com/MickLesk) ([#10035](https://github.com/community-scripts/ProxmoxVE/pull/10035))
|
||||||
|
- pdm: add rsyslog to fix /dev/log Connection refused errors [@MickLesk](https://github.com/MickLesk) ([#10018](https://github.com/community-scripts/ProxmoxVE/pull/10018))
|
||||||
|
- 2fauth: bump to php8.4 [@MickLesk](https://github.com/MickLesk) ([#10019](https://github.com/community-scripts/ProxmoxVE/pull/10019))
|
||||||
|
- Miniflux: use correct systemctl to check service instead of file path [@MickLesk](https://github.com/MickLesk) ([#10024](https://github.com/community-scripts/ProxmoxVE/pull/10024))
|
||||||
|
- PhotoPrism: export env variables for CLI tools [@MickLesk](https://github.com/MickLesk) ([#10023](https://github.com/community-scripts/ProxmoxVE/pull/10023))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- core: IP-Range-Scan Support (app.vars / default.vars) [@MickLesk](https://github.com/MickLesk) ([#10038](https://github.com/community-scripts/ProxmoxVE/pull/10038))
|
||||||
|
- tools.func: add optional enabled parameter to setup_deb822_repo [@MickLesk](https://github.com/MickLesk) ([#10017](https://github.com/community-scripts/ProxmoxVE/pull/10017))
|
||||||
|
- core: map Etc/* timezones to 'host' for pct compatibility [@MickLesk](https://github.com/MickLesk) ([#10020](https://github.com/community-scripts/ProxmoxVE/pull/10020))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- website: bump deps & prevent security issues [@MickLesk](https://github.com/MickLesk) ([#10045](https://github.com/community-scripts/ProxmoxVE/pull/10045))
|
||||||
|
|
||||||
|
## 2025-12-15
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- Koel ([#9972](https://github.com/community-scripts/ProxmoxVE/pull/9972))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fix DiscoPanel build [@PouletteMC](https://github.com/PouletteMC) ([#10009](https://github.com/community-scripts/ProxmoxVE/pull/10009))
|
||||||
|
- fix:ct/openwebui.sh adding progressbar and minimize service downtime [@jobben-2025](https://github.com/jobben-2025) ([#9894](https://github.com/community-scripts/ProxmoxVE/pull/9894))
|
||||||
|
- homarr: add: temp note aboute deb13 requirement [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9992](https://github.com/community-scripts/ProxmoxVE/pull/9992))
|
||||||
|
- paperless-ai: backup data and recreate venv during update [@MickLesk](https://github.com/MickLesk) ([#9987](https://github.com/community-scripts/ProxmoxVE/pull/9987))
|
||||||
|
- fix(booklore): add setup_yq to update script [@MickLesk](https://github.com/MickLesk) ([#9989](https://github.com/community-scripts/ProxmoxVE/pull/9989))
|
||||||
|
- fix(pangolin-install): add network-online dependency [@worried-networking](https://github.com/worried-networking) ([#9984](https://github.com/community-scripts/ProxmoxVE/pull/9984))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- OPNsense: dynamic crawl latest stable FreeBSD [@austindsmith](https://github.com/austindsmith) ([#9831](https://github.com/community-scripts/ProxmoxVE/pull/9831))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Refactor: Heimdall Dashboard [@tremor021](https://github.com/tremor021) ([#9959](https://github.com/community-scripts/ProxmoxVE/pull/9959))
|
||||||
|
|
||||||
|
### 💾 Core
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- tools: prevent awk errors in setup_rust on restricted containers [@MickLesk](https://github.com/MickLesk) ([#9985](https://github.com/community-scripts/ProxmoxVE/pull/9985))
|
||||||
|
- core: App Defaults force mode and prevent unbound variables [@MickLesk](https://github.com/MickLesk) ([#9971](https://github.com/community-scripts/ProxmoxVE/pull/9971))
|
||||||
|
- core: load app defaults before applying base_settings / fix composer cleanup after install/update [@MickLesk](https://github.com/MickLesk) ([#9965](https://github.com/community-scripts/ProxmoxVE/pull/9965))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- tools: handle flat repositories in setup_deb822_repo [@MickLesk](https://github.com/MickLesk) ([#9994](https://github.com/community-scripts/ProxmoxVE/pull/9994))
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
|
||||||
|
- (github) remove old files and assets [@MickLesk](https://github.com/MickLesk) ([#9991](https://github.com/community-scripts/ProxmoxVE/pull/9991))
|
||||||
|
- README; add project statistics / formatting [@MickLesk](https://github.com/MickLesk) ([#9967](https://github.com/community-scripts/ProxmoxVE/pull/9967))
|
||||||
|
|
||||||
## 2025-12-14
|
## 2025-12-14
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- SonarQube: Fix database variables [@tremor021](https://github.com/tremor021) ([#9946](https://github.com/community-scripts/ProxmoxVE/pull/9946))
|
||||||
|
|
||||||
|
- #### 💥 Breaking Changes
|
||||||
|
|
||||||
|
- refactor: homarr [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9948](https://github.com/community-scripts/ProxmoxVE/pull/9948))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- Update dependencies and remove unused files [@BramSuurdje](https://github.com/BramSuurdje) ([#9945](https://github.com/community-scripts/ProxmoxVE/pull/9945))
|
||||||
|
|
||||||
## 2025-12-13
|
## 2025-12-13
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|||||||
33
README.md
33
README.md
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
> **Simplify your Proxmox VE setup with community-driven automation scripts**
|
**Simplify your Proxmox VE setup with community-driven automation scripts**
|
||||||
> Originally created by tteck, now maintained and expanded by the community
|
Originally created by tteck, now maintained and expanded by the community
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -239,17 +239,34 @@ This project is maintained by volunteers in memory of tteck. Your support helps
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📈 Project Growth
|
## 📈 Project Statistics
|
||||||
|
<p align="center">
|
||||||
|
<img
|
||||||
|
src="https://repobeats.axiom.co/api/embed/57edde03e00f88d739bdb5b844ff7d07dd079375.svg"
|
||||||
|
alt="Repobeats analytics"
|
||||||
|
width="650"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
|
||||||
<div align="center">
|
<p align="center">
|
||||||
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
|
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark" />
|
<source
|
||||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
|
media="(prefers-color-scheme: dark)"
|
||||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
|
srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark"
|
||||||
|
/>
|
||||||
|
<source
|
||||||
|
media="(prefers-color-scheme: light)"
|
||||||
|
srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
alt="Star History Chart"
|
||||||
|
src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date"
|
||||||
|
width="650"
|
||||||
|
/>
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -28,20 +28,21 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "2fauth" "Bubka/2FAuth"; then
|
if check_for_gh_release "2fauth" "Bubka/2FAuth"; then
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt -y upgrade
|
$STD apt -y upgrade
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
msg_info "Creating Backup"
|
||||||
mv "/opt/2fauth" "/opt/2fauth-backup"
|
mv "/opt/2fauth" "/opt/2fauth-backup"
|
||||||
if ! dpkg -l | grep -q 'php8.3'; then
|
if ! dpkg -l | grep -q 'php8.4'; then
|
||||||
cp /etc/nginx/conf.d/2fauth.conf /etc/nginx/conf.d/2fauth.conf.bak
|
cp /etc/nginx/conf.d/2fauth.conf /etc/nginx/conf.d/2fauth.conf.bak
|
||||||
fi
|
fi
|
||||||
msg_ok "Backup Created"
|
msg_ok "Backup Created"
|
||||||
|
|
||||||
if ! dpkg -l | grep -q 'php8.3'; then
|
if ! dpkg -l | grep -q 'php8.4'; then
|
||||||
PHP_VERSION="8.3" PHP_MODULE="common,ctype,fileinfo,mysql,cli,tokenizer,dom,redis,session,openssl" PHP_FPM="YES" setup_php
|
PHP_VERSION="8.4" PHP_MODULE="common,ctype,fileinfo,mysql,cli,tokenizer,dom,redis,session,openssl" PHP_FPM="YES" setup_php
|
||||||
sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/2fauth.conf
|
sed -i 's/php8\.[0-9]/php8.4/g' /etc/nginx/conf.d/2fauth.conf
|
||||||
fi
|
fi
|
||||||
fetch_and_deploy_gh_release "2fauth" "Bubka/2FAuth"
|
fetch_and_deploy_gh_release "2fauth" "Bubka/2FAuth"
|
||||||
setup_composer
|
setup_composer
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-ubuntu}"
|
var_os="${var_os:-ubuntu}"
|
||||||
var_version="${var_version:-24.04}"
|
var_version="${var_version:-24.04}"
|
||||||
var_unprivileged="${var_unprivileged:-0}"
|
var_unprivileged="${var_unprivileged:-0}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_error "Currently we don't provide an update function for this ${APP}."
|
msg_error "Currently we don't provide an update function for this ${APP}."
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
|
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop booklore
|
systemctl stop booklore
|
||||||
@ -46,6 +47,7 @@ function update_script() {
|
|||||||
msg_ok "Built Frontend"
|
msg_ok "Built Frontend"
|
||||||
|
|
||||||
JAVA_VERSION="21" setup_java
|
JAVA_VERSION="21" setup_java
|
||||||
|
setup_yq
|
||||||
|
|
||||||
msg_info "Building Backend"
|
msg_info "Building Backend"
|
||||||
cd /opt/booklore/booklore-api
|
cd /opt/booklore/booklore-api
|
||||||
|
|||||||
@ -28,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "bookstack" "BookStackApp/BookStack"; then
|
if check_for_gh_release "bookstack" "BookStackApp/BookStack"; then
|
||||||
msg_info "Stopping Apache2"
|
msg_info "Stopping Apache2"
|
||||||
systemctl stop apache2
|
systemctl stop apache2
|
||||||
|
|||||||
@ -1,138 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2025 tteck
|
|
||||||
# Author: tteck (tteckster) | Co-Author: remz1337
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/janeczku/calibre-web
|
|
||||||
|
|
||||||
APP="Calibre-Web"
|
|
||||||
var_tags="${var_tags:-eBook}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-2048}"
|
|
||||||
var_disk="${var_disk:-4}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-12}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
if [[ ! -f /etc/systemd/system/cps.service ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop cps
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
msg_info "Updating ${APP}"
|
|
||||||
cd /opt/kepubify
|
|
||||||
rm -rf kepubify-linux-64bit
|
|
||||||
curl -fsSLO https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-64bit
|
|
||||||
chmod +x kepubify-linux-64bit
|
|
||||||
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
|
|
||||||
"3" "Enables displaying of additional author infos on the authors page" OFF
|
|
||||||
"4" "Enables login via LDAP server" OFF
|
|
||||||
"5" "Enables login via google or github oauth" OFF
|
|
||||||
"6" "Enables extracting of metadata from epub, fb2, pdf files, and also extraction of covers from cbr, cbz, cbt files" OFF
|
|
||||||
"7" "Enables extracting of metadata from cbr, cbz, cbt files" OFF
|
|
||||||
"8" "Enables syncing with your kobo reader" OFF)
|
|
||||||
if [ -f "/opt/calibre-web/options.txt" ]; then
|
|
||||||
cps_options="$(cat /opt/calibre-web/options.txt)"
|
|
||||||
IFS=',' read -ra ADDR <<<"$cps_options"
|
|
||||||
for i in "${ADDR[@]}"; do
|
|
||||||
if [ $i == "gdrive" ]; then
|
|
||||||
line=0
|
|
||||||
elif [ $i == "gmail" ]; then
|
|
||||||
line=1
|
|
||||||
elif [ $i == "goodreads" ]; then
|
|
||||||
line=2
|
|
||||||
elif [ $i == "ldap" ]; then
|
|
||||||
line=3
|
|
||||||
elif [ $i == "oauth" ]; then
|
|
||||||
line=4
|
|
||||||
elif [ $i == "metadata" ]; then
|
|
||||||
line=5
|
|
||||||
elif [ $i == "comics" ]; then
|
|
||||||
line=6
|
|
||||||
elif [ $i == "kobo" ]; then
|
|
||||||
line=7
|
|
||||||
fi
|
|
||||||
array_index=$((3 * line + 2))
|
|
||||||
menu_array[$array_index]=ON
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
|
|
||||||
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_PID=$!
|
|
||||||
options=()
|
|
||||||
if [ ! -z "$CHOICES" ]; then
|
|
||||||
for CHOICE in $CHOICES; do
|
|
||||||
case "$CHOICE" in
|
|
||||||
"1")
|
|
||||||
options+=(gdrive)
|
|
||||||
;;
|
|
||||||
"2")
|
|
||||||
options+=(gmail)
|
|
||||||
;;
|
|
||||||
"3")
|
|
||||||
options+=(goodreads)
|
|
||||||
;;
|
|
||||||
"4")
|
|
||||||
options+=(ldap)
|
|
||||||
apt-get install -qqy libldap2-dev libsasl2-dev
|
|
||||||
;;
|
|
||||||
"5")
|
|
||||||
options+=(oauth)
|
|
||||||
;;
|
|
||||||
"6")
|
|
||||||
options+=(metadata)
|
|
||||||
;;
|
|
||||||
"7")
|
|
||||||
options+=(comics)
|
|
||||||
;;
|
|
||||||
"8")
|
|
||||||
options+=(kobo)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported item $CHOICE!" >&2
|
|
||||||
exit
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if [ ${#options[@]} -gt 0 ]; then
|
|
||||||
cps_options=$(
|
|
||||||
IFS=,
|
|
||||||
echo "${options[*]}"
|
|
||||||
)
|
|
||||||
echo $cps_options >/opt/calibre-web/options.txt
|
|
||||||
$STD pip install --upgrade calibreweb[$cps_options]
|
|
||||||
else
|
|
||||||
rm -rf /opt/calibre-web/options.txt
|
|
||||||
$STD pip install --upgrade calibreweb
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start cps
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8083${CL}"
|
|
||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-25}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-20}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-12}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -49,6 +49,8 @@ function update_script() {
|
|||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "discopanel" "nickheyer/discopanel" "tarball" "latest" "/opt/discopanel"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "discopanel" "nickheyer/discopanel" "tarball" "latest" "/opt/discopanel"
|
||||||
|
|
||||||
msg_info "Setting up DiscoPanel"
|
msg_info "Setting up DiscoPanel"
|
||||||
|
cd /opt/discopanel
|
||||||
|
$STD make gen
|
||||||
cd /opt/discopanel/web/discopanel
|
cd /opt/discopanel/web/discopanel
|
||||||
$STD npm install
|
$STD npm install
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
@ -89,7 +90,7 @@ function update_script() {
|
|||||||
|
|
||||||
if ! grep -q "DJANGO_SECRET_KEY" /opt/dispatcharr/.env; then
|
if ! grep -q "DJANGO_SECRET_KEY" /opt/dispatcharr/.env; then
|
||||||
DJANGO_SECRET=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | cut -c1-50)
|
DJANGO_SECRET=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | cut -c1-50)
|
||||||
echo "DJANGO_SECRET_KEY=$DJANGO_SECRET" >> /opt/dispatcharr/.env
|
echo "DJANGO_SECRET_KEY=$DJANGO_SECRET" >>/opt/dispatcharr/.env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd /opt/dispatcharr
|
cd /opt/dispatcharr
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_error "To update ${APP}, use the applications web interface."
|
msg_error "To update ${APP}, use the applications web interface."
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
if ! grep -Fq "root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then
|
if ! grep -Fq "root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then
|
||||||
echo "0 0 * * * root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab
|
echo "0 0 * * * root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab
|
||||||
|
|||||||
@ -28,7 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} installation found!"
|
msg_error "No ${APP} installation found!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if check_for_gh_release "endurain" "joaovitoriasilva/endurain"; then
|
if check_for_gh_release "endurain" "endurain-project/endurain"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop endurain
|
systemctl stop endurain
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
@ -38,7 +38,7 @@ function update_script() {
|
|||||||
cp /opt/endurain/frontend/app/dist/env.js /opt/endurain.env.js
|
cp /opt/endurain/frontend/app/dist/env.js /opt/endurain.env.js
|
||||||
msg_ok "Created Backup"
|
msg_ok "Created Backup"
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "endurain" "joaovitoriasilva/endurain" "tarball" "latest" "/opt/endurain"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "endurain" "endurain-project/endurain" "tarball" "latest" "/opt/endurain"
|
||||||
|
|
||||||
msg_info "Preparing Update"
|
msg_info "Preparing Update"
|
||||||
cd /opt/endurain
|
cd /opt/endurain
|
||||||
|
|||||||
@ -28,7 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then
|
if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then
|
||||||
systemctl stop apache2
|
systemctl stop apache2
|
||||||
cp /opt/firefly/.env /opt/.env
|
cp /opt/firefly/.env /opt/.env
|
||||||
|
|||||||
@ -23,6 +23,7 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
NODE_VERSION="22" setup_nodejs
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
|
RELEASE=$(curl -fsSL https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
|
||||||
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_error "Currently we don't provide an update function for this ${APP}."
|
msg_error "Currently we don't provide an update function for this ${APP}."
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-4}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-12}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
______ ___ __ _ __ __
|
|
||||||
/ ____/___ _/ (_) /_ ________ | | / /__ / /_
|
|
||||||
/ / / __ `/ / / __ \/ ___/ _ \_____| | /| / / _ \/ __ \
|
|
||||||
/ /___/ /_/ / / / /_/ / / / __/_____/ |/ |/ / __/ /_/ /
|
|
||||||
\____/\__,_/_/_/_.___/_/ \___/ |__/|__/\___/_.___/
|
|
||||||
|
|
||||||
6
ct/headers/koel
Normal file
6
ct/headers/koel
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
__ __ __
|
||||||
|
/ //_/___ ___ / /
|
||||||
|
/ ,< / __ \/ _ \/ /
|
||||||
|
/ /| / /_/ / __/ /
|
||||||
|
/_/ |_\____/\___/_/
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
_ __ __ _ ___
|
_____
|
||||||
/ | / /__ / /| | / (_)________ _____
|
/ ___/_________ _____ ____ ____ __ __
|
||||||
/ |/ / _ \/ __/ | / / / ___/ __ \/ ___/
|
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / /
|
||||||
/ /| / __/ /_ | |/ / (__ ) /_/ / /
|
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ /
|
||||||
/_/ |_/\___/\__/ |___/_/____/\____/_/
|
/____/\___/\__,_/_/ /_/\____/ .___/\__, /
|
||||||
|
/_/ /____/
|
||||||
|
|||||||
6
ct/headers/scanopy
Normal file
6
ct/headers/scanopy
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
_____
|
||||||
|
/ ___/_________ _____ ____ ____ __ __
|
||||||
|
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / /
|
||||||
|
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ /
|
||||||
|
/____/\___/\__,_/_/ /_/\____/ .___/\__, /
|
||||||
|
/_/ /____/
|
||||||
@ -11,7 +11,7 @@ var_cpu="${var_cpu:-1}"
|
|||||||
var_ram="${var_ram:-512}"
|
var_ram="${var_ram:-512}"
|
||||||
var_disk="${var_disk:-2}"
|
var_disk="${var_disk:-2}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
@ -27,45 +27,45 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
RELEASE=$(curl -fsSL "https://api.github.com/repos/linuxserver/Heimdall/releases/latest" | awk '/tag_name/{print $4;exit}' FS='[""]')
|
|
||||||
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
|
if check_for_gh_release "Heimdall" "linuxserver/Heimdall"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop heimdall
|
systemctl stop heimdall
|
||||||
sleep 1
|
sleep 1
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Backing up Data"
|
msg_info "Backing up Data"
|
||||||
cp -R /opt/Heimdall/database database-backup
|
cp -R /opt/Heimdall/database database-backup
|
||||||
cp -R /opt/Heimdall/public public-backup
|
cp -R /opt/Heimdall/public public-backup
|
||||||
sleep 1
|
sleep 1
|
||||||
msg_ok "Backed up Data"
|
msg_ok "Backed up Data"
|
||||||
msg_info "Updating Heimdall Dashboard to ${RELEASE}"
|
|
||||||
curl -fsSL "https://github.com/linuxserver/Heimdall/archive/${RELEASE}.tar.gz" -o $(basename "https://github.com/linuxserver/Heimdall/archive/${RELEASE}.tar.gz")
|
setup_composer
|
||||||
tar xzf "${RELEASE}".tar.gz
|
fetch_and_deploy_gh_release "Heimdall" "linuxserver/Heimdall" "tarball"
|
||||||
VER=$(curl -fsSL https://api.github.com/repos/linuxserver/Heimdall/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
|
||||||
cp -R Heimdall-"${VER}"/* /opt/Heimdall
|
msg_info "Updating Heimdall-Dashboard"
|
||||||
cd /opt/Heimdall
|
cd /opt/Heimdall
|
||||||
$STD apt-get install -y composer
|
|
||||||
export COMPOSER_ALLOW_SUPERUSER=1
|
export COMPOSER_ALLOW_SUPERUSER=1
|
||||||
$STD composer dump-autoload
|
$STD composer dump-autoload
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
msg_ok "Updated Heimdall-Dashboard"
|
||||||
msg_ok "Updated Heimdall Dashboard to ${RELEASE}"
|
|
||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
cd ~
|
cd ~
|
||||||
cp -R database-backup/* /opt/Heimdall/database
|
cp -R database-backup/* /opt/Heimdall/database
|
||||||
cp -R public-backup/* /opt/Heimdall/public
|
cp -R public-backup/* /opt/Heimdall/public
|
||||||
sleep 1
|
sleep 1
|
||||||
msg_ok "Restored Data"
|
msg_ok "Restored Data"
|
||||||
msg_info "Cleanup"
|
|
||||||
rm -rf {"${RELEASE}".tar.gz,Heimdall-"${VER}",public-backup,database-backup,Heimdall}
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf {public-backup,database-backup}
|
||||||
sleep 1
|
sleep 1
|
||||||
msg_ok "Cleaned"
|
msg_ok "Cleaned Up"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start heimdall.service
|
systemctl start heimdall.service
|
||||||
sleep 2
|
sleep 2
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}."
|
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
155
ct/homarr.sh
155
ct/homarr.sh
@ -1,21 +1,20 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: CrazyWolf13
|
# Author: MickLesk (CanbiZ) | Co-Author: CrazyWolf13
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://homarr.dev/
|
# Source: https://homarr.dev/
|
||||||
|
|
||||||
APP="homarr"
|
APP="homarr"
|
||||||
var_tags="${var_tags:-arr;dashboard}"
|
var_tags="${var_tags:-arr;dashboard}"
|
||||||
var_cpu="${var_cpu:-3}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-6144}"
|
var_ram="${var_ram:-1024}"
|
||||||
var_disk="${var_disk:-8}"
|
var_disk="${var_disk:-8}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
|
|
||||||
variables
|
variables
|
||||||
color
|
color
|
||||||
catch_errors
|
catch_errors
|
||||||
@ -28,69 +27,43 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
if [[ -f /opt/homarr/database/db.sqlite ]]; then
|
|
||||||
msg_error "Old Homarr detected due to existing database file (/opt/homarr/database/db.sqlite)."
|
|
||||||
msg_error "Update not supported. Refer to:"
|
|
||||||
msg_error " - https://github.com/community-scripts/ProxmoxVE/discussions/1551"
|
|
||||||
msg_error " - https://homarr.dev/docs/getting-started/after-the-installation/#importing-a-zip-from-version-before-100"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if [[ ! -f /opt/run_homarr.sh ]]; then
|
|
||||||
msg_info "Detected outdated and missing service files"
|
|
||||||
msg_error "Warning - The port of homarr changed from 3000 to 7575"
|
|
||||||
$STD apt-get install -y nginx gettext openssl gpg
|
|
||||||
sed -i '/^NODE_ENV=/d' /opt/homarr/.env && echo "NODE_ENV='production'" >>/opt/homarr/.env
|
|
||||||
sed -i '/^DB_DIALECT=/d' /opt/homarr/.env && echo "DB_DIALECT='sqlite'" >>/opt/homarr/.env
|
|
||||||
cat <<'EOF' >/opt/run_homarr.sh
|
|
||||||
#!/bin/bash
|
|
||||||
set -a
|
|
||||||
source /opt/homarr/.env
|
|
||||||
set +a
|
|
||||||
export DB_DIALECT='sqlite'
|
|
||||||
export AUTH_SECRET=$(openssl rand -base64 32)
|
|
||||||
export CRON_JOB_API_KEY=$(openssl rand -base64 32)
|
|
||||||
node /opt/homarr_db/migrations/$DB_DIALECT/migrate.cjs /opt/homarr_db/migrations/$DB_DIALECT
|
|
||||||
for dir in $(find /opt/homarr_db/migrations/migrations -mindepth 1 -maxdepth 1 -type d); do
|
|
||||||
dirname=$(basename "$dir")
|
|
||||||
mkdir -p "/opt/homarr_db/migrations/$dirname"
|
|
||||||
cp -r "$dir"/* "/opt/homarr_db/migrations/$dirname/" 2>/dev/null || true
|
|
||||||
done
|
|
||||||
export HOSTNAME=$(ip route get 1.1.1.1 | grep -oP 'src \K[^ ]+')
|
|
||||||
envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf
|
|
||||||
nginx -g 'daemon off;' &
|
|
||||||
redis-server /opt/homarr/packages/redis/redis.conf &
|
|
||||||
node apps/tasks/tasks.cjs &
|
|
||||||
node apps/websocket/wssServer.cjs &
|
|
||||||
node apps/nextjs/server.js & PID=$!
|
|
||||||
wait $PID
|
|
||||||
EOF
|
|
||||||
chmod +x /opt/run_homarr.sh
|
|
||||||
rm /etc/systemd/system/homarr.service
|
|
||||||
cat <<EOF >/etc/systemd/system/homarr.service
|
|
||||||
[Unit]
|
|
||||||
Description=Homarr Service
|
|
||||||
After=network.target
|
|
||||||
[Service]
|
|
||||||
Type=exec
|
|
||||||
WorkingDirectory=/opt/homarr
|
|
||||||
EnvironmentFile=-/opt/homarr/.env
|
|
||||||
ExecStart=/opt/run_homarr.sh
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
msg_ok "Updated Services"
|
|
||||||
systemctl daemon-reload
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "homarr" "homarr-labs/homarr"; then
|
if check_for_gh_release "homarr" "homarr-labs/homarr"; then
|
||||||
msg_info "Stopping Services (Patience)"
|
msg_info "Stopping Services (Patience)"
|
||||||
systemctl stop homarr
|
systemctl stop homarr
|
||||||
|
systemctl stop redis-server
|
||||||
msg_ok "Services Stopped"
|
msg_ok "Services Stopped"
|
||||||
|
|
||||||
msg_info "Backup Data"
|
if ! { grep -q '^REDIS_IS_EXTERNAL=' /opt/homarr/.env 2>/dev/null || grep -q '^REDIS_IS_EXTERNAL=' /opt/homarr.env 2>/dev/null; }; then
|
||||||
mkdir -p /opt/homarr-data-backup
|
DEBIAN_VERSION=$(cat /etc/debian_version 2>/dev/null | cut -d'.' -f1)
|
||||||
cp /opt/homarr/.env /opt/homarr-data-backup/.env
|
if [[ -n "$DEBIAN_VERSION" ]] && [[ "$DEBIAN_VERSION" -lt 13 ]]; then
|
||||||
msg_ok "Backup Data"
|
msg_warn "⚠️ COMPATIBILITY WARNING ⚠️"
|
||||||
|
msg_warn "You are running Debian ${DEBIAN_VERSION}. Homarr's requires Debian 13"
|
||||||
|
msg_warn ""
|
||||||
|
msg_warn "Please Upgrade to Debian 13:"
|
||||||
|
msg_warn "See: https://github.com/community-scripts/ProxmoxVE/discussions/7489"
|
||||||
|
msg_warn ""
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
msg_info "Fixing old structure"
|
||||||
|
# fix musl issues because homarr compiles on alpine not debian soure: https://github.com/alexander-akhmetov/python-telegram/issues/3
|
||||||
|
$STD apt install -y musl-dev
|
||||||
|
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1
|
||||||
|
cp /opt/homarr/.env /opt/homarr.env
|
||||||
|
echo "REDIS_IS_EXTERNAL='true'" >> /opt/homarr.env
|
||||||
|
sed -i 's|^ExecStart=.*|ExecStart=/opt/homarr/run.sh|' /etc/systemd/system/homarr.service
|
||||||
|
sed -i 's|^EnvironmentFile=.*|EnvironmentFile=-/opt/homarr.env|' /etc/systemd/system/homarr.service
|
||||||
|
chown -R redis:redis /appdata/redis
|
||||||
|
chmod 744 /appdata/redis
|
||||||
|
mkdir -p /etc/systemd/system/redis-server.service.d/
|
||||||
|
cat <<EOF >/etc/systemd/system/redis-server.service.d/override.conf
|
||||||
|
[Service]
|
||||||
|
ReadWritePaths=-/appdata/redis -/var/lib/redis -/var/log/redis -/var/run/redis -/etc/redis
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload
|
||||||
|
rm /opt/run_homarr.sh
|
||||||
|
msg_ok "Fixed old structure"
|
||||||
|
fi
|
||||||
|
|
||||||
msg_info "Updating Nodejs"
|
msg_info "Updating Nodejs"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
@ -98,69 +71,21 @@ EOF
|
|||||||
msg_ok "Updated Nodejs"
|
msg_ok "Updated Nodejs"
|
||||||
|
|
||||||
NODE_VERSION=$(curl -s https://raw.githubusercontent.com/homarr-labs/homarr/dev/package.json | jq -r '.engines.node | split(">=")[1] | split(".")[0]')
|
NODE_VERSION=$(curl -s https://raw.githubusercontent.com/homarr-labs/homarr/dev/package.json | jq -r '.engines.node | split(">=")[1] | split(".")[0]')
|
||||||
NODE_MODULE="pnpm@$(curl -s https://raw.githubusercontent.com/homarr-labs/homarr/dev/package.json | jq -r '.packageManager | split("@")[1]')"
|
|
||||||
setup_nodejs
|
setup_nodejs
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "homarr" "homarr-labs/homarr" "prebuild" "latest" "/opt/homarr" "build-amd64.tar.gz"
|
||||||
|
|
||||||
rm -rf /opt/homarr
|
msg_info "Updating Homarr"
|
||||||
fetch_and_deploy_gh_release "homarr" "homarr-labs/homarr"
|
cp /opt/homarr/redis.conf /etc/redis/redis.conf
|
||||||
|
|
||||||
msg_info "Updating and rebuilding ${APP} (Patience)"
|
|
||||||
rm /opt/run_homarr.sh
|
|
||||||
cat <<'EOF' >/opt/run_homarr.sh
|
|
||||||
#!/bin/bash
|
|
||||||
set -a
|
|
||||||
source /opt/homarr/.env
|
|
||||||
set +a
|
|
||||||
export DB_DIALECT='sqlite'
|
|
||||||
export AUTH_SECRET=$(openssl rand -base64 32)
|
|
||||||
export CRON_JOB_API_KEY=$(openssl rand -base64 32)
|
|
||||||
node /opt/homarr_db/migrations/$DB_DIALECT/migrate.cjs /opt/homarr_db/migrations/$DB_DIALECT
|
|
||||||
for dir in $(find /opt/homarr_db/migrations/migrations -mindepth 1 -maxdepth 1 -type d); do
|
|
||||||
dirname=$(basename "$dir")
|
|
||||||
mkdir -p "/opt/homarr_db/migrations/$dirname"
|
|
||||||
cp -r "$dir"/* "/opt/homarr_db/migrations/$dirname/" 2>/dev/null || true
|
|
||||||
done
|
|
||||||
export HOSTNAME=$(ip route get 1.1.1.1 | grep -oP 'src \K[^ ]+')
|
|
||||||
envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf
|
|
||||||
nginx -g 'daemon off;' &
|
|
||||||
redis-server /opt/homarr/packages/redis/redis.conf &
|
|
||||||
node apps/tasks/tasks.cjs &
|
|
||||||
node apps/websocket/wssServer.cjs &
|
|
||||||
node apps/nextjs/server.js & PID=$!
|
|
||||||
wait $PID
|
|
||||||
EOF
|
|
||||||
chmod +x /opt/run_homarr.sh
|
|
||||||
mv /opt/homarr-data-backup/.env /opt/homarr/.env
|
|
||||||
cd /opt/homarr
|
|
||||||
$STD pnpm install --recursive --frozen-lockfile --shamefully-hoist
|
|
||||||
$STD pnpm build
|
|
||||||
cp /opt/homarr/apps/nextjs/next.config.ts .
|
|
||||||
cp /opt/homarr/apps/nextjs/package.json .
|
|
||||||
cp -r /opt/homarr/packages/db/migrations /opt/homarr_db/migrations
|
|
||||||
cp -r /opt/homarr/apps/nextjs/.next/standalone/* /opt/homarr
|
|
||||||
mkdir -p /appdata/redis
|
|
||||||
cp /opt/homarr/packages/redis/redis.conf /opt/homarr/redis.conf
|
|
||||||
rm /etc/nginx/nginx.conf
|
rm /etc/nginx/nginx.conf
|
||||||
mkdir -p /etc/nginx/templates
|
|
||||||
cp /opt/homarr/nginx.conf /etc/nginx/templates/nginx.conf
|
cp /opt/homarr/nginx.conf /etc/nginx/templates/nginx.conf
|
||||||
|
msg_ok "Updated Homarr"
|
||||||
mkdir -p /opt/homarr/apps/cli
|
|
||||||
cp /opt/homarr/packages/cli/cli.cjs /opt/homarr/apps/cli/cli.cjs
|
|
||||||
echo $'#!/bin/bash\ncd /opt/homarr/apps/cli && node ./cli.cjs "$@"' >/usr/bin/homarr
|
|
||||||
chmod +x /usr/bin/homarr
|
|
||||||
|
|
||||||
mkdir /opt/homarr/build
|
|
||||||
cp ./node_modules/better-sqlite3/build/Release/better_sqlite3.node ./build/better_sqlite3.node
|
|
||||||
msg_ok "Updated ${APP}"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
|
chmod +x /opt/homarr/run.sh
|
||||||
systemctl start homarr
|
systemctl start homarr
|
||||||
|
systemctl start redis-server
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
read -p "${TAB3}It's recommended to reboot the LXC after an update, would you like to reboot the LXC now ? (y/n): " choice
|
|
||||||
if [[ "$choice" =~ ^[Yy]$ ]]; then
|
|
||||||
reboot
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "hortusfox" "danielbrendel/hortusfox-web"; then
|
if check_for_gh_release "hortusfox" "danielbrendel/hortusfox-web"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop apache2
|
systemctl stop apache2
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-4}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-12}"
|
||||||
var_unprivileged="${var_unprivileged:-0}"
|
var_unprivileged="${var_unprivileged:-0}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-2}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -28,7 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "invoiceninja" "invoiceninja/invoiceninja"; then
|
if check_for_gh_release "invoiceninja" "invoiceninja/invoiceninja"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop supervisor nginx php8.4-fpm
|
systemctl stop supervisor nginx php8.4-fpm
|
||||||
|
|||||||
@ -28,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
msg_info "Updating LXC"
|
msg_info "Updating LXC"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
|
|||||||
@ -30,6 +30,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" setup_php
|
PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" setup_php
|
||||||
setup_composer
|
setup_composer
|
||||||
|
|||||||
81
ct/koel.sh
Normal file
81
ct/koel.sh
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: MickLesk (CanbiZ)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://koel.dev/
|
||||||
|
|
||||||
|
APP="Koel"
|
||||||
|
var_tags="${var_tags:-music;streaming}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-8}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-13}"
|
||||||
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -d /opt/koel ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "koel" "koel/koel"; then
|
||||||
|
msg_info "Stopping Services"
|
||||||
|
systemctl stop nginx php8.4-fpm
|
||||||
|
msg_ok "Stopped Services"
|
||||||
|
|
||||||
|
msg_info "Creating Backup"
|
||||||
|
mkdir -p /tmp/koel_backup
|
||||||
|
cp /opt/koel/.env /tmp/koel_backup/
|
||||||
|
cp -r /opt/koel/storage /tmp/koel_backup/ 2>/dev/null || true
|
||||||
|
cp -r /opt/koel/public/img /tmp/koel_backup/ 2>/dev/null || true
|
||||||
|
msg_ok "Created Backup"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "koel" "koel/koel" "prebuild" "latest" "/opt/koel" "koel-*.tar.gz"
|
||||||
|
|
||||||
|
msg_info "Restoring Data"
|
||||||
|
cp /tmp/koel_backup/.env /opt/koel/
|
||||||
|
cp -r /tmp/koel_backup/storage/* /opt/koel/storage/ 2>/dev/null || true
|
||||||
|
cp -r /tmp/koel_backup/img/* /opt/koel/public/img/ 2>/dev/null || true
|
||||||
|
rm -rf /tmp/koel_backup
|
||||||
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
|
msg_info "Running Migrations"
|
||||||
|
cd /opt/koel
|
||||||
|
export COMPOSER_ALLOW_SUPERUSER=1
|
||||||
|
$STD composer install --no-interaction --no-dev --optimize-autoloader
|
||||||
|
$STD php artisan migrate --force
|
||||||
|
$STD php artisan config:clear
|
||||||
|
$STD php artisan cache:clear
|
||||||
|
$STD php artisan view:clear
|
||||||
|
$STD php artisan koel:init --no-assets --no-interaction
|
||||||
|
chown -R www-data:www-data /opt/koel
|
||||||
|
chmod -R 775 /opt/koel/storage
|
||||||
|
msg_ok "Ran Migrations"
|
||||||
|
|
||||||
|
msg_info "Starting Services"
|
||||||
|
systemctl start php8.4-fpm nginx
|
||||||
|
msg_ok "Started Services"
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
||||||
@ -28,7 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "leantime" "Leantime/leantime"; then
|
if check_for_gh_release "leantime" "Leantime/leantime"; then
|
||||||
msg_info "Creating Backup"
|
msg_info "Creating Backup"
|
||||||
mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql"
|
mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql"
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_info "Updating LibreNMS"
|
msg_info "Updating LibreNMS"
|
||||||
su librenms
|
su librenms
|
||||||
cd /opt/librenms
|
cd /opt/librenms
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-20}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
msg_warn "Application is updated via Web Interface"
|
msg_warn "Application is updated via Web Interface"
|
||||||
exit
|
exit
|
||||||
|
|||||||
@ -28,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "mmdl" "intri-in/manage-my-damn-life-nextjs"; then
|
if check_for_gh_release "mmdl" "intri-in/manage-my-damn-life-nextjs"; then
|
||||||
msg_info "Stopping service"
|
msg_info "Stopping service"
|
||||||
systemctl stop mmdl
|
systemctl stop mmdl
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP} LXC"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt -y upgrade
|
$STD apt -y upgrade
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-4}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -23,7 +23,7 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -f /etc/systemd/system/miniflux.service ]]; then
|
if ! systemctl -q is-enabled miniflux 2>/dev/null; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
|
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -3,9 +3,9 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
|||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: vhsdream
|
# Author: vhsdream
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://github.com/netvisor-io/netvisor
|
# Source: https://github.com/scanopy/scanopy
|
||||||
|
|
||||||
APP="NetVisor"
|
APP="Scanopy"
|
||||||
var_tags="${var_tags:-analytics}"
|
var_tags="${var_tags:-analytics}"
|
||||||
var_cpu="${var_cpu:-2}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-3072}"
|
var_ram="${var_ram:-3072}"
|
||||||
@ -29,19 +29,12 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "netvisor" "netvisor-io/netvisor"; then
|
|
||||||
msg_info "Stopping services"
|
msg_info "Stopping services"
|
||||||
systemctl stop netvisor-daemon netvisor-server
|
systemctl -q disable --now netvisor-daemon netvisor-server
|
||||||
msg_ok "Stopped services"
|
msg_ok "Stopped services"
|
||||||
|
|
||||||
msg_info "Backing up configurations"
|
NODE_VERSION="24" setup_nodejs
|
||||||
cp /opt/netvisor/.env /opt/netvisor.env.bak
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
||||||
if [[ -f /opt/netvisor/oidc.toml ]]; then
|
|
||||||
cp /opt/netvisor/oidc.toml /opt/netvisor.oidc.toml
|
|
||||||
fi
|
|
||||||
msg_ok "Backed up configurations"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "netvisor-io/netvisor" "tarball" "latest" "/opt/netvisor"
|
|
||||||
|
|
||||||
if ! dpkg -l | grep -q "pkg-config"; then
|
if ! dpkg -l | grep -q "pkg-config"; then
|
||||||
$STD apt install -y pkg-config
|
$STD apt install -y pkg-config
|
||||||
@ -49,51 +42,61 @@ function update_script() {
|
|||||||
if ! dpkg -l | grep -q "libssl-dev"; then
|
if ! dpkg -l | grep -q "libssl-dev"; then
|
||||||
$STD apt install -y libssl-dev
|
$STD apt install -y libssl-dev
|
||||||
fi
|
fi
|
||||||
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
||||||
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
||||||
|
|
||||||
mv /opt/netvisor.env.bak /opt/netvisor/.env
|
mv /opt/netvisor/.env /opt/scanopy/.env
|
||||||
if [[ -f /opt/netvisor.oidc.toml ]]; then
|
if [[ -f /opt/netvisor/oidc.toml ]]; then
|
||||||
mv /opt/netvisor.oidc.toml /opt/netvisor/oidc.toml
|
mv /opt/netvisor/oidc.toml /opt/scanopy/oidc.toml
|
||||||
fi
|
fi
|
||||||
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
||||||
if ! grep -q "PUBLIC_URL" /opt/netvisor/.env; then
|
if ! grep -q "PUBLIC_URL" /opt/scanopy/.env; then
|
||||||
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/netvisor/.env
|
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/scanopy/.env
|
||||||
fi
|
fi
|
||||||
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/netvisor/.env
|
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/scanopy/.env
|
||||||
|
sed -i 's/NETVISOR/SCANOPY/g; s|netvisor/|scanopy/|' /opt/scanopy/.env
|
||||||
|
|
||||||
msg_info "Creating frontend UI"
|
msg_info "Creating frontend UI"
|
||||||
export PUBLIC_SERVER_HOSTNAME=default
|
export PUBLIC_SERVER_HOSTNAME=default
|
||||||
export PUBLIC_SERVER_PORT=""
|
export PUBLIC_SERVER_PORT=""
|
||||||
cd /opt/netvisor/ui
|
cd /opt/scanopy/ui
|
||||||
$STD npm ci --no-fund --no-audit
|
$STD npm ci --no-fund --no-audit
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
msg_ok "Created frontend UI"
|
msg_ok "Created frontend UI"
|
||||||
|
|
||||||
msg_info "Building Netvisor-server (patience)"
|
msg_info "Building Scanopy-server (patience)"
|
||||||
cd /opt/netvisor/backend
|
cd /opt/scanopy/backend
|
||||||
$STD cargo build --release --bin server
|
$STD cargo build --release --bin server
|
||||||
mv ./target/release/server /usr/bin/netvisor-server
|
mv ./target/release/server /usr/bin/scanopy-server
|
||||||
msg_ok "Built Netvisor-server"
|
msg_ok "Built Scanopy-server"
|
||||||
|
|
||||||
msg_info "Building Netvisor-daemon"
|
msg_info "Building Scanopy-daemon"
|
||||||
$STD cargo build --release --bin daemon
|
$STD cargo build --release --bin daemon
|
||||||
cp ./target/release/daemon /usr/bin/netvisor-daemon
|
cp ./target/release/daemon /usr/bin/scanopy-daemon
|
||||||
msg_ok "Built Netvisor-daemon"
|
msg_ok "Built Scanopy-daemon"
|
||||||
|
|
||||||
|
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
|
||||||
sed -i -e 's|-target|-url|' \
|
sed -i -e 's|-target|-url|' \
|
||||||
-e 's| --server-port |:|' \
|
-e 's| --server-port |:|' \
|
||||||
|
-e 's/NetVisor/Scanopy/' \
|
||||||
|
-e 's/netvisor/scanopy/' \
|
||||||
/etc/systemd/system/netvisor-daemon.service
|
/etc/systemd/system/netvisor-daemon.service
|
||||||
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
|
mv /etc/systemd/system/netvisor-daemon.service /etc/systemd/system/scanopy-daemon.service
|
||||||
if ! grep -q "WorkingD" /etc/systemd/system/netvisor-server.service; then
|
sed -i -e 's/NetVisor/Scanopy/' \
|
||||||
sed -i '\|simple$|a\WorkingDirectory=/opt/netvisor/backend' /etc/systemd/system/netvisor-server.service
|
-e 's/netvisor/scanopy/g' \
|
||||||
fi
|
/etc/systemd/system/netvisor-server.service
|
||||||
|
mv /etc/systemd/system/netvisor-server.service /etc/systemd/system/scanopy-server.service
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
|
|
||||||
msg_info "Starting services"
|
msg_info "Starting services"
|
||||||
systemctl start netvisor-server netvisor-daemon
|
systemctl -q enable --now scanopy-server scanopy-daemon
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
|
||||||
|
sed -i 's/netvisor/scanopy/' /usr/bin/update
|
||||||
|
mv ~/NetVisor.creds ~/scanopy.creds
|
||||||
|
rm ~/.netvisor
|
||||||
|
rm -rf /opt/netvisor
|
||||||
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ var_disk="${var_disk:-5}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-ubuntu}"
|
var_os="${var_os:-ubuntu}"
|
||||||
var_version="${var_version:-24.04}"
|
var_version="${var_version:-24.04}"
|
||||||
var_unprivileged="${var_unprivileged:-0}"
|
var_unprivileged="${var_unprivileged:-0}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -88,22 +88,36 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -x "/usr/bin/ollama" ]; then
|
if [ -x "/usr/bin/ollama" ]; then
|
||||||
msg_info "Updating Ollama"
|
msg_info "Checking for Ollama Update"
|
||||||
OLLAMA_VERSION=$(ollama -v | awk '{print $NF}')
|
OLLAMA_VERSION=$(ollama -v | awk '{print $NF}')
|
||||||
RELEASE=$(curl -s https://api.github.com/repos/ollama/ollama/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4)}')
|
RELEASE=$(curl -s https://api.github.com/repos/ollama/ollama/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4)}')
|
||||||
if [ "$OLLAMA_VERSION" != "$RELEASE" ]; then
|
if [ "$OLLAMA_VERSION" != "$RELEASE" ]; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Ollama update available: v$OLLAMA_VERSION -> v$RELEASE"
|
||||||
|
msg_info "Downloading Ollama v$RELEASE \n"
|
||||||
|
curl -fS#LO https://ollama.com/download/ollama-linux-amd64.tgz
|
||||||
|
msg_ok "Download Complete"
|
||||||
|
|
||||||
|
if [ -f "ollama-linux-amd64.tgz" ]; then
|
||||||
|
|
||||||
|
msg_info "Stopping Ollama Service"
|
||||||
systemctl stop ollama
|
systemctl stop ollama
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
curl -fsSLO -C - https://ollama.com/download/ollama-linux-amd64.tgz
|
|
||||||
|
msg_info "Installing Ollama"
|
||||||
rm -rf /usr/lib/ollama
|
rm -rf /usr/lib/ollama
|
||||||
rm -rf /usr/bin/ollama
|
rm -rf /usr/bin/ollama
|
||||||
tar -C /usr -xzf ollama-linux-amd64.tgz
|
tar -C /usr -xzf ollama-linux-amd64.tgz
|
||||||
rm -rf ollama-linux-amd64.tgz
|
rm -rf ollama-linux-amd64.tgz
|
||||||
msg_info "Starting Service"
|
msg_ok "Installed Ollama"
|
||||||
|
|
||||||
|
msg_info "Starting Ollama Service"
|
||||||
systemctl start ollama
|
systemctl start ollama
|
||||||
msg_info "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
msg_ok "Ollama updated to version $RELEASE"
|
msg_ok "Ollama updated to version $RELEASE"
|
||||||
|
else
|
||||||
|
msg_error "Ollama download failed. Aborting update."
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
msg_ok "Ollama is already up to date."
|
msg_ok "Ollama is already up to date."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-2}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -33,10 +33,23 @@ function update_script() {
|
|||||||
systemctl stop paperless-ai paperless-rag
|
systemctl stop paperless-ai paperless-rag
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Backing up data"
|
||||||
|
cp -r /opt/paperless-ai/data /opt/paperless-ai-data-backup
|
||||||
|
msg_ok "Backed up data"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "paperless-ai" "clusterzx/paperless-ai"
|
fetch_and_deploy_gh_release "paperless-ai" "clusterzx/paperless-ai"
|
||||||
|
|
||||||
|
msg_info "Restoring data"
|
||||||
|
cp -r /opt/paperless-ai-data-backup/* /opt/paperless-ai/data/
|
||||||
|
rm -rf /opt/paperless-ai-data-backup
|
||||||
|
msg_ok "Restored data"
|
||||||
|
|
||||||
msg_info "Updating Paperless-AI"
|
msg_info "Updating Paperless-AI"
|
||||||
cd /opt/paperless-ai
|
cd /opt/paperless-ai
|
||||||
|
if [[ ! -d /opt/paperless-ai/venv ]]; then
|
||||||
|
msg_info "Recreating Python venv"
|
||||||
|
$STD python3 -m venv /opt/paperless-ai/venv
|
||||||
|
fi
|
||||||
source /opt/paperless-ai/venv/bin/activate
|
source /opt/paperless-ai/venv/bin/activate
|
||||||
$STD pip install --upgrade pip
|
$STD pip install --upgrade pip
|
||||||
$STD pip install --no-cache-dir -r requirements.txt
|
$STD pip install --no-cache-dir -r requirements.txt
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_info "Updating $APP LXC"
|
msg_info "Updating $APP LXC"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt upgrade -y
|
$STD apt upgrade -y
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||||
if [[ "$CURRENT_PHP" != "8.3" ]]; then
|
if [[ "$CURRENT_PHP" != "8.3" ]]; then
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||||
|
|
||||||
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
@ -32,6 +33,13 @@ function update_script() {
|
|||||||
systemctl stop photoprism
|
systemctl stop photoprism
|
||||||
msg_ok "Stopped PhotoPrism"
|
msg_ok "Stopped PhotoPrism"
|
||||||
|
|
||||||
|
if ! grep -q "photoprism/config/.env" ~/.bashrc 2>/dev/null; then
|
||||||
|
msg_info "Adding environment export for CLI tools"
|
||||||
|
echo '# Load PhotoPrism environment variables for CLI tools' >>~/.bashrc
|
||||||
|
echo 'export $(grep -v "^#" /opt/photoprism/config/.env | xargs)' >>~/.bashrc
|
||||||
|
msg_ok "Added environment export"
|
||||||
|
fi
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "photoprism" "photoprism/photoprism" "prebuild" "latest" "/opt/photoprism" "*linux-amd64.tar.gz"
|
fetch_and_deploy_gh_release "photoprism" "photoprism/photoprism" "prebuild" "latest" "/opt/photoprism" "*linux-amd64.tar.gz"
|
||||||
|
|
||||||
LIBHEIF_URL=$(curl -fsSL "https://dl.photoprism.app/dist/libheif/" | grep -oP "libheif-bookworm-amd64-v[0-9\.]+\.tar\.gz" | sort -V | tail -n 1)
|
LIBHEIF_URL=$(curl -fsSL "https://dl.photoprism.app/dist/libheif/" | grep -oP "libheif-bookworm-amd64-v[0-9\.]+\.tar\.gz" | sort -V | tail -n 1)
|
||||||
|
|||||||
@ -27,7 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "phpipam" "phpipam/phpipam"; then
|
if check_for_gh_release "phpipam" "phpipam/phpipam"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop apache2
|
systemctl stop apache2
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then
|
if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop plant-it
|
systemctl stop plant-it
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
if check_for_gh_release "projectsend" "projectsend/projectsend"; then
|
if check_for_gh_release "projectsend" "projectsend/projectsend"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||||
|
|
||||||
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
||||||
|
|||||||
@ -23,29 +23,23 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -f /usr/local/bin/wings ]]; then
|
if [[ ! -x /usr/local/bin/wings ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/pterodactyl/wings/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
|
if check_for_gh_release "wings" "pterodactyl/wings"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop wings
|
systemctl stop wings
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Updating ${APP} to v${RELEASE}"
|
|
||||||
rm /usr/local/bin/wings
|
rm /usr/local/bin/wings
|
||||||
curl -fsSL "https://github.com/pterodactyl/wings/releases/download/v${RELEASE}/wings_linux_amd64" -o "/usr/local/bin/wings"
|
fetch_and_deploy_gh_release "wings" "pterodactyl/wings" "singlefile" "latest" "/usr/local/bin" "wings_linux_amd64"
|
||||||
chmod u+x /usr/local/bin/wings
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start wings
|
systemctl start wings
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,16 +29,11 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
if grep -q "dl.cloudsmith.io" /etc/apt/sources.list.d/rabbitmq.list; then
|
if grep -q "dl.cloudsmith.io" /etc/apt/sources.list.d/rabbitmq.list; then
|
||||||
rm -f /etc/apt/sources.list.d/rabbitmq.list
|
rm -f /etc/apt/sources.list.d/rabbitmq.list
|
||||||
cat <<EOF >/etc/apt/sources.list.d/rabbitmq.list
|
setup_deb822_repo \
|
||||||
## Modern Erlang/OTP releases
|
"rabbitmq" \
|
||||||
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-erlang/debian/trixie trixie main
|
"https://keys.openpgp.org/vks/v1/by-fingerprint/0A9AF2115F4687BD29803A206B73A36E6026DFCA" \
|
||||||
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-erlang/debian/trixie trixie main
|
"https://deb1.rabbitmq.com/rabbitmq-server/debian/trixie" \
|
||||||
|
"trixie"
|
||||||
## Provides modern RabbitMQ releases
|
|
||||||
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb1.rabbitmq.com/rabbitmq-server/debian/trixie trixie main
|
|
||||||
deb [arch=amd64 signed-by=/usr/share/keyrings/com.rabbitmq.team.gpg] https://deb2.rabbitmq.com/rabbitmq-server/debian/trixie trixie main
|
|
||||||
EOF
|
|
||||||
$STD apt update
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
|
|||||||
@ -41,7 +41,7 @@ function update_script() {
|
|||||||
cp -R /opt/rdtc-backup/appsettings.json /opt/rdtc/
|
cp -R /opt/rdtc-backup/appsettings.json /opt/rdtc/
|
||||||
if dpkg-query -W dotnet-sdk-8.0 >/dev/null 2>&1; then
|
if dpkg-query -W dotnet-sdk-8.0 >/dev/null 2>&1; then
|
||||||
$STD apt remove --purge -y dotnet-sdk-8.0
|
$STD apt remove --purge -y dotnet-sdk-8.0
|
||||||
$STD apt install -y dotnet-sdk-9.0
|
$STD apt install -y aspnetcore-runtime-9.0
|
||||||
fi
|
fi
|
||||||
rm -rf /opt/rdtc-backup
|
rm -rf /opt/rdtc-backup
|
||||||
|
|
||||||
|
|||||||
@ -33,12 +33,11 @@ function update_script() {
|
|||||||
systemctl stop Reactive-Resume
|
systemctl stop Reactive-Resume
|
||||||
msg_ok "Stopped services"
|
msg_ok "Stopped services"
|
||||||
|
|
||||||
cp /opt/"$APP"/.env /opt/rxresume.env
|
cp /opt/Reactive-Resume/.env /opt/rxresume.env
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "Reactive-Resume" "lazy-media/Reactive-Resume" "tarball" "latest" "/opt/Reactive-Resume"
|
fetch_and_deploy_gh_release "Reactive-Resume" "lazy-media/Reactive-Resume" "tarball" "latest" "/opt/Reactive-Resume"
|
||||||
|
|
||||||
msg_info "Updating $APP"
|
msg_info "Updating Reactive-Resume"
|
||||||
cd /opt/"$APP"
|
cd /opt/Reactive-Resume
|
||||||
export PUPPETEER_SKIP_DOWNLOAD="true"
|
export PUPPETEER_SKIP_DOWNLOAD="true"
|
||||||
export NEXT_TELEMETRY_DISABLED=1
|
export NEXT_TELEMETRY_DISABLED=1
|
||||||
export CI="true"
|
export CI="true"
|
||||||
@ -46,8 +45,8 @@ function update_script() {
|
|||||||
$STD pnpm install --frozen-lockfile
|
$STD pnpm install --frozen-lockfile
|
||||||
$STD pnpm run build
|
$STD pnpm run build
|
||||||
$STD pnpm run prisma:generate
|
$STD pnpm run prisma:generate
|
||||||
mv /opt/rxresume.env /opt/"$APP"/.env
|
mv /opt/rxresume.env /opt/Reactive-Resume/.env
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated Reactive-Resume"
|
||||||
|
|
||||||
msg_info "Updating Minio"
|
msg_info "Updating Minio"
|
||||||
systemctl stop minio
|
systemctl stop minio
|
||||||
|
|||||||
@ -27,9 +27,10 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Updating $APP LXC"
|
msg_info "Updating $APP LXC"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt -y upgrade
|
$STD apt upgrade -y
|
||||||
msg_ok "Updated $APP LXC"
|
msg_ok "Updated $APP LXC"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
|
|||||||
@ -27,9 +27,9 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating Resilio Sync"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt -y upgrade
|
$STD apt upgrade -y
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,16 +29,14 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/saltstack/salt/releases/latest | jq -r .tag_name | sed 's/^v//')
|
RELEASE=$(get_latest_github_release "saltstack/salt")
|
||||||
if [[ ! -f /~.salt ]] || [[ "${RELEASE}" != "$(cat /~.salt)" ]]; then
|
if check_for_gh_release "salt" "saltstack/salt"; then
|
||||||
msg_info "Updating $APP to ${RELEASE}"
|
msg_info "Updating Salt"
|
||||||
sed -i "s/^\(Pin: version \).*/\1${RELEASE}/" /etc/apt/preferences.d/salt-pin-1001
|
sed -i "s/^\(Pin: version \).*/\1${RELEASE}/" /etc/apt/preferences.d/salt-pin-1001
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt upgrade -y
|
$STD apt upgrade -y
|
||||||
echo "${RELEASE}" >/~.salt
|
echo "${RELEASE}" >/~.salt
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
|
||||||
msg_ok "${APP} is already up to date (${RELEASE})"
|
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
99
ct/scanopy.sh
Normal file
99
ct/scanopy.sh
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: vhsdream
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://github.com/scanopy/scanopy
|
||||||
|
|
||||||
|
APP="Scanopy"
|
||||||
|
var_tags="${var_tags:-analytics}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-3072}"
|
||||||
|
var_disk="${var_disk:-6}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-13}"
|
||||||
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -d /opt/scanopy ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "scanopy" "scanopy/scanopy"; then
|
||||||
|
msg_info "Stopping services"
|
||||||
|
systemctl stop scanopy-daemon scanopy-server
|
||||||
|
msg_ok "Stopped services"
|
||||||
|
|
||||||
|
msg_info "Backing up configurations"
|
||||||
|
cp /opt/scanopy/.env /opt/scanopy.env.bak
|
||||||
|
if [[ -f /opt/scanopy/oidc.toml ]]; then
|
||||||
|
cp /opt/scanopy/oidc.toml /opt/scanopy.oidc.toml
|
||||||
|
fi
|
||||||
|
msg_ok "Backed up configurations"
|
||||||
|
|
||||||
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "scanopy" "scanopy/scanopy" "tarball" "latest" "/opt/scanopy"
|
||||||
|
|
||||||
|
if ! dpkg -l | grep -q "pkg-config"; then
|
||||||
|
$STD apt install -y pkg-config
|
||||||
|
fi
|
||||||
|
if ! dpkg -l | grep -q "libssl-dev"; then
|
||||||
|
$STD apt install -y libssl-dev
|
||||||
|
fi
|
||||||
|
TOOLCHAIN="$(grep "channel" /opt/scanopy/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
||||||
|
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
||||||
|
|
||||||
|
mv /opt/scanopy.env.bak /opt/scanopy/.env
|
||||||
|
if [[ -f /opt/scanopy.oidc.toml ]]; then
|
||||||
|
mv /opt/scanopy.oidc.toml /opt/scanopy/oidc.toml
|
||||||
|
fi
|
||||||
|
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
||||||
|
if ! grep -q "PUBLIC_URL" /opt/scanopy/.env; then
|
||||||
|
sed -i "\|_PATH=|a\scanopy_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/scanopy/.env
|
||||||
|
fi
|
||||||
|
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/scanopy/.env
|
||||||
|
|
||||||
|
msg_info "Creating frontend UI"
|
||||||
|
export PUBLIC_SERVER_HOSTNAME=default
|
||||||
|
export PUBLIC_SERVER_PORT=""
|
||||||
|
cd /opt/scanopy/ui
|
||||||
|
$STD npm ci --no-fund --no-audit
|
||||||
|
$STD npm run build
|
||||||
|
msg_ok "Created frontend UI"
|
||||||
|
|
||||||
|
msg_info "Building scanopy-server (patience)"
|
||||||
|
cd /opt/scanopy/backend
|
||||||
|
$STD cargo build --release --bin server
|
||||||
|
mv ./target/release/server /usr/bin/scanopy-server
|
||||||
|
msg_ok "Built scanopy-server"
|
||||||
|
|
||||||
|
msg_info "Building scanopy-daemon"
|
||||||
|
$STD cargo build --release --bin daemon
|
||||||
|
cp ./target/release/daemon /usr/bin/scanopy-daemon
|
||||||
|
msg_ok "Built scanopy-daemon"
|
||||||
|
|
||||||
|
msg_info "Starting services"
|
||||||
|
systemctl start scanopy-server scanopy-daemon
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
fi
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:60072${CL}"
|
||||||
|
echo -e "${INFO}${YW} Then create your account, and run the 'configure_daemon.sh' script to setup the daemon.${CL}"
|
||||||
@ -33,7 +33,7 @@ function update_script() {
|
|||||||
systemctl stop semaphore
|
systemctl stop semaphore
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "semaphore" "semaphoreui/semaphore" "binary"
|
fetch_and_deploy_gh_release "semaphore" "semaphoreui/semaphore" "binary" "latest" "/opt/semaphore" "semaphore_*_linux_amd64.deb"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start semaphore
|
systemctl start semaphore
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-ubuntu}"
|
var_os="${var_os:-ubuntu}"
|
||||||
var_version="${var_version:-24.04}"
|
var_version="${var_version:-24.04}"
|
||||||
var_unprivileged="${var_unprivileged:-0}"
|
var_unprivileged="${var_unprivileged:-0}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
@ -27,6 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_info "Updating Shinobi"
|
msg_info "Updating Shinobi"
|
||||||
cd /opt/Shinobi
|
cd /opt/Shinobi
|
||||||
$STD sh UPDATE.sh
|
$STD sh UPDATE.sh
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then
|
if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then
|
||||||
sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf
|
sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -34,7 +34,7 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Updating Telegraf"
|
msg_info "Updating Telegraf"
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD apt upgrade telegraf -y
|
$STD apt upgrade -y telegraf
|
||||||
msg_ok "Updated Telegraf"
|
msg_ok "Updated Telegraf"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-4}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -34,38 +34,39 @@ function update_script() {
|
|||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Correcting Services"
|
msg_info "Correcting Services"
|
||||||
if [ -f /opt/tracktor/app/backend/.env ]; then
|
|
||||||
mv /opt/tracktor/app/backend/.env /opt/tracktor.env
|
|
||||||
echo 'AUTH_PIN=123456' >>/opt/tracktor.env
|
|
||||||
sed -i 's|^EnvironmentFile=.*|EnvironmentFile=/opt/tracktor.env|' /etc/systemd/system/tracktor.service
|
|
||||||
systemctl daemon-reload
|
|
||||||
fi
|
|
||||||
if [ ! -d "/opt/tracktor-data/uploads" ]; then
|
if [ ! -d "/opt/tracktor-data/uploads" ]; then
|
||||||
mkdir -p /opt/tracktor-data/{uploads,logs}
|
mkdir -p /opt/tracktor-data/{uploads,logs}
|
||||||
EXISTING_AUTH_PIN=$(grep '^AUTH_PIN=' /opt/tracktor.env 2>/dev/null | cut -d'=' -f2)
|
fi
|
||||||
AUTH_PIN=${EXISTING_AUTH_PIN:-123456}
|
if ! grep -qxF 'BODY_SIZE_LIMIT=Infinity' /opt/tracktor.env; then
|
||||||
|
rm /opt/tracktor.env
|
||||||
cat <<EOF >/opt/tracktor.env
|
cat <<EOF >/opt/tracktor.env
|
||||||
|
cat <<EOF >/opt/tracktor.env
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
# Set this to the path of the database file. Default - ./tracktor.db
|
||||||
DB_PATH=/opt/tracktor-data/tracktor.db
|
DB_PATH=/opt/tracktor-data/tracktor.db
|
||||||
|
# Set this to the path of the uploads directory. Default - ./uploads
|
||||||
UPLOADS_DIR="/opt/tracktor-data/uploads"
|
UPLOADS_DIR="/opt/tracktor-data/uploads"
|
||||||
|
# Set this to the path of the logs directory. Default - ./logs
|
||||||
LOG_DIR="/opt/tracktor-data/logs"
|
LOG_DIR="/opt/tracktor-data/logs"
|
||||||
# If server host is not set by default it will run on all interfaces - 0.0.0.0
|
# Hostname to bind the server to. Default - 0.0.0.0
|
||||||
# SERVER_HOST=""
|
#HOST="0.0.0.0"
|
||||||
SERVER_PORT=3000
|
# Port to bind the server to. Default - 3000
|
||||||
# Set this if you want to secure your endpoints otherwise default will be "*"
|
#PORT=3000
|
||||||
CORS_ORIGINS="*"
|
# Set this to remove upload size limitations. Default - 512 Kb
|
||||||
# Set this if you are using backend and frontend separately.
|
BODY_SIZE_LIMIT=Infinity
|
||||||
# PUBLIC_API_BASE_URL=""
|
# Enable request logging. Default - true
|
||||||
LOG_REQUESTS=true
|
#LOG_REQUESTS=true
|
||||||
LOG_LEVEL="info"
|
# Set the logging level. Options - error, warn, info, verbose, debug, silly. Default - info
|
||||||
AUTH_PIN=${AUTH_PIN}
|
#LOG_LEVEL="info"
|
||||||
# PUBLIC_DEMO_MODE=false
|
# Enable demo mode. Default - false
|
||||||
# FORCE_DATA_SEED=false
|
#TRACKTOR_DEMO_MODE=false
|
||||||
|
# Force reseeding of data on every startup. Default - false
|
||||||
|
#FORCE_DATA_SEED=false
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
msg_ok "Corrected Services"
|
msg_ok "Corrected Services"
|
||||||
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
NODE_VERSION="24" setup_nodejs
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tracktor" "javedh-dev/tracktor" "tarball" "latest" "/opt/tracktor"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tracktor" "javedh-dev/tracktor" "tarball" "latest" "/opt/tracktor"
|
||||||
|
|
||||||
msg_info "Updating tracktor"
|
msg_info "Updating tracktor"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ var_disk="${var_disk:-8}"
|
|||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
var_gpu="${var_gpu:-yes}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables
|
||||||
|
|||||||
@ -28,7 +28,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "wallabag" "wallabag/wallabag"; then
|
if check_for_gh_release "wallabag" "wallabag/wallabag"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop nginx php8.3-fpm
|
systemctl stop nginx php8.3-fpm
|
||||||
|
|||||||
@ -27,7 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
if check_for_gh_release "wavelog" "wavelog/wavelog"; then
|
if check_for_gh_release "wavelog" "wavelog/wavelog"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop apache2
|
systemctl stop apache2
|
||||||
|
|||||||
@ -27,6 +27,7 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
setup_mariadb
|
||||||
msg_error "Wordpress should be updated via the user interface."
|
msg_error "Wordpress should be updated via the user interface."
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,7 +67,7 @@ function update_script() {
|
|||||||
|
|
||||||
rm -Rf /etc/apt/sources.list.d/zabbix.list
|
rm -Rf /etc/apt/sources.list.d/zabbix.list
|
||||||
cd /tmp
|
cd /tmp
|
||||||
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
||||||
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
|
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
|
||||||
$STD dpkg -i zabbix-release_latest+debian13_all.deb
|
$STD dpkg -i zabbix-release_latest+debian13_all.deb
|
||||||
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
|
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
|
||||||
|
|||||||
@ -434,12 +434,24 @@ var_unprivileged=1 # 0=privileged, 1=unprivileged
|
|||||||
#### Network
|
#### Network
|
||||||
```bash
|
```bash
|
||||||
var_brg=vmbr0 # Bridge interface
|
var_brg=vmbr0 # Bridge interface
|
||||||
var_net=veth # Network driver
|
var_net=dhcp # dhcp, static IP/CIDR, or IP range (see below)
|
||||||
var_gateway=192.168.1.1 # Default gateway
|
var_gateway=192.168.1.1 # Default gateway (required for static IP)
|
||||||
var_mtu=1500 # MTU size
|
var_mtu=1500 # MTU size
|
||||||
var_vlan=100 # VLAN ID
|
var_vlan=100 # VLAN ID
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### IP Range Scanning
|
||||||
|
|
||||||
|
You can specify an IP range instead of a static IP. The system will ping each IP in the range and automatically assign the first free IP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Format: START_IP/CIDR-END_IP/CIDR
|
||||||
|
var_net=192.168.1.100/24-192.168.1.200/24
|
||||||
|
var_gateway=192.168.1.1
|
||||||
|
```
|
||||||
|
|
||||||
|
This is useful for automated deployments where you want static IPs but don't want to track which IPs are already in use.
|
||||||
|
|
||||||
#### System
|
#### System
|
||||||
```bash
|
```bash
|
||||||
var_hostname=pihole # Container name
|
var_hostname=pihole # Container name
|
||||||
|
|||||||
@ -122,6 +122,31 @@ var_verbose=no \
|
|||||||
echo "✓ Container deployed successfully"
|
echo "✓ Container deployed successfully"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Using IP Range Scan for Automatic IP Assignment
|
||||||
|
|
||||||
|
Instead of manually specifying static IPs, you can define an IP range. The system will automatically ping each IP and assign the first free one:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# deploy-with-ip-scan.sh - Auto-assign first free IP from range
|
||||||
|
|
||||||
|
var_unprivileged=1 \
|
||||||
|
var_cpu=4 \
|
||||||
|
var_ram=4096 \
|
||||||
|
var_hostname=web-server \
|
||||||
|
var_net=192.168.1.100/24-192.168.1.150/24 \
|
||||||
|
var_gateway=192.168.1.1 \
|
||||||
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/debian.sh)"
|
||||||
|
|
||||||
|
# The script will:
|
||||||
|
# 1. Ping 192.168.1.100 - if responds, skip
|
||||||
|
# 2. Ping 192.168.1.101 - if responds, skip
|
||||||
|
# 3. Continue until first IP that doesn't respond
|
||||||
|
# 4. Assign that IP to the container
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**: IP range format is `START_IP/CIDR-END_IP/CIDR`. Both sides must include the same CIDR notation.
|
||||||
|
|
||||||
### Using App Defaults
|
### Using App Defaults
|
||||||
|
|
||||||
**Step 1: Create defaults once (interactive)**
|
**Step 1: Create defaults once (interactive)**
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
dist
|
|
||||||
node_modules
|
|
||||||
.next
|
|
||||||
build
|
|
||||||
.contentlayer
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-organize-imports"]
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2024 Bram Suurd
|
Copyright (c) 2024-Present Bram Suurd
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
663
frontend/bun.lock
generated
663
frontend/bun.lock
generated
File diff suppressed because it is too large
Load Diff
104
frontend/package.json
generated
104
frontend/package.json
generated
@ -16,80 +16,70 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-accordion": "^1.2.3",
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
"@radix-ui/react-dialog": "^1.1.6",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-icons": "^1.3.2",
|
"@radix-ui/react-icons": "^1.3.2",
|
||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.8",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.5",
|
"@radix-ui/react-navigation-menu": "^1.2.14",
|
||||||
"@radix-ui/react-popover": "^1.1.6",
|
"@radix-ui/react-popover": "^1.1.15",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.10",
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
"@radix-ui/react-switch": "^1.1.3",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
"@radix-ui/react-tabs": "^1.1.3",
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-tooltip": "^1.2.0",
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
"@tanstack/react-query": "^5.71.1",
|
"@tanstack/react-query": "^5.90.12",
|
||||||
"chart.js": "^4.4.8",
|
"chart.js": "^4.5.1",
|
||||||
"chartjs-plugin-datalabels": "^2.2.0",
|
"chartjs-plugin-datalabels": "^2.2.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
"framer-motion": "^12.23.26",
|
||||||
"framer-motion": "^11.18.2",
|
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"lucide-react": "^0.554.0",
|
"lucide-react": "^0.561.0",
|
||||||
"mini-svg-data-uri": "^1.4.4",
|
"mini-svg-data-uri": "^1.4.4",
|
||||||
"motion": "^12.23.12",
|
"motion": "^12.23.26",
|
||||||
"next": "15.5.7",
|
"next": "15.5.8",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.6",
|
||||||
"nuqs": "^2.4.1",
|
"nuqs": "^2.8.5",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"react": "19.2.3",
|
||||||
"react": "19.0.0",
|
"react-chartjs-2": "^5.3.1",
|
||||||
"react-chartjs-2": "^5.3.0",
|
"react-code-blocks": "^0.1.6",
|
||||||
"react-day-picker": "^9.4.3",
|
"react-datepicker": "^9.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-day-picker": "^9.12.0",
|
||||||
|
"react-dom": "19.2.3",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-use-measure": "^2.1.7",
|
"react-use-measure": "^2.1.7",
|
||||||
"recharts": "2.15.4",
|
"recharts": "3.6.0",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.34.5",
|
||||||
"sonner": "^1.7.4",
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^3.4.0",
|
||||||
"zod": "^3.24.2"
|
"zod": "^4.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^4.16.1",
|
"@antfu/eslint-config": "^6.7.1",
|
||||||
"@eslint-react/eslint-plugin": "^1.52.2",
|
"@eslint-react/eslint-plugin": "^2.3.13",
|
||||||
"@next/eslint-plugin-next": "^15.3.4",
|
"@next/eslint-plugin-next": "^15.5.8",
|
||||||
"@tanstack/eslint-plugin-query": "^5.68.0",
|
"@tanstack/eslint-plugin-query": "^5.91.2",
|
||||||
"@types/node": "^22.13.16",
|
"@types/node": "^25.0.2",
|
||||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.29.0",
|
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
||||||
"@typescript-eslint/parser": "^8.29.0",
|
"@typescript-eslint/parser": "^8.50.0",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^5.1.2",
|
||||||
"eslint": "^9.23.0",
|
"eslint": "^9.39.2",
|
||||||
"eslint-config-next": "15.0.2",
|
"eslint-config-next": "15.5.8",
|
||||||
"eslint-plugin-format": "^1.0.1",
|
"eslint-plugin-format": "^1.1.0",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.25",
|
||||||
"jsdom": "^25.0.1",
|
"jsdom": "^27.3.0",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.5.3",
|
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"tailwindcss-animated": "^1.1.2",
|
"tailwindcss-animated": "^1.1.2",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.9.3"
|
||||||
"vite-tsconfig-paths": "^5.1.4"
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
|
||||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"react": "19.0.0",
|
|
||||||
"react-dom": "19.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
"ram": 512,
|
"ram": 512,
|
||||||
"hdd": 2,
|
"hdd": 2,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -19,8 +19,8 @@
|
|||||||
"type": "default",
|
"type": "default",
|
||||||
"script": "ct/homarr.sh",
|
"script": "ct/homarr.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 3,
|
"cpu": 2,
|
||||||
"ram": 6144,
|
"ram": 1024,
|
||||||
"hdd": 8,
|
"hdd": 8,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "13"
|
"version": "13"
|
||||||
|
|||||||
48
frontend/public/json/koel.json
Normal file
48
frontend/public/json/koel.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "Koel",
|
||||||
|
"slug": "koel",
|
||||||
|
"categories": [
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"date_created": "2025-12-15",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 80,
|
||||||
|
"documentation": "https://docs.koel.dev/",
|
||||||
|
"config_path": "/opt/koel/.env",
|
||||||
|
"website": "https://koel.dev/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/koel-light.webp",
|
||||||
|
"description": "Koel is a simple web-based personal audio streaming service written in Vue and Laravel. It supports multiple users, audio visualization, smart playlists, YouTube integration, and Last.fm scrobbling.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/koel.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 2048,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": "admin@koel.dev",
|
||||||
|
"password": "KoelIsCool"
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Media files should be placed in /opt/koel_media",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Database credentials are stored in ~/koel.creds",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Music library is scanned hourly via cron job",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@
|
|||||||
"documentation": "https://pterodactyl.io/wings/1.0/installing.html",
|
"documentation": "https://pterodactyl.io/wings/1.0/installing.html",
|
||||||
"website": "https://pterodactyl.io",
|
"website": "https://pterodactyl.io",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/pterodactyl.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/pterodactyl.webp",
|
||||||
"config_path": "",
|
"config_path": "/etc/pterodactyl/config.yml",
|
||||||
"description": "Pterodactyl Wings is Pterodactyl's server control plane, built for the rapidly changing gaming industry and designed to be highly performant and secure. Wings provides an HTTP API allowing you to interface directly with running server instances, fetch server logs, generate backups, and control all aspects of the server lifecycle.",
|
"description": "Pterodactyl Wings is Pterodactyl's server control plane, built for the rapidly changing gaming industry and designed to be highly performant and secure. Wings provides an HTTP API allowing you to interface directly with running server instances, fetch server logs, generate backups, and control all aspects of the server lifecycle.",
|
||||||
"install_methods": [
|
"install_methods": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "NetVisor",
|
"name": "Scanopy",
|
||||||
"slug": "netvisor",
|
"slug": "scanopy",
|
||||||
"categories": [
|
"categories": [
|
||||||
9
|
9
|
||||||
],
|
],
|
||||||
@ -9,15 +9,15 @@
|
|||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 60072,
|
"interface_port": 60072,
|
||||||
"documentation": "https://github.com/netvisor-io/netvisor",
|
"documentation": "https://github.com/scanopy/scanopy",
|
||||||
"config_path": "/opt/netvisor/.env, OIDC: /opt/netvisor/oidc.toml",
|
"config_path": "/opt/scanopy/.env, OIDC: /opt/scanopy/oidc.toml",
|
||||||
"website": "https://netvisor.io",
|
"website": "https://scanopy.net",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/netvisor.png",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/scanopy.webp",
|
||||||
"description": "Automatically discover and visually document network infrastructure",
|
"description": "Automatically discover and visually document network infrastructure",
|
||||||
"install_methods": [
|
"install_methods": [
|
||||||
{
|
{
|
||||||
"type": "default",
|
"type": "default",
|
||||||
"script": "ct/netvisor.sh",
|
"script": "ct/scanopy.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 2,
|
"cpu": 2,
|
||||||
"ram": 3072,
|
"ram": 3072,
|
||||||
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
export const InstallMethodSchema = z.object({
|
export const InstallMethodSchema = z.object({
|
||||||
type: z.enum(["default", "alpine"], {
|
type: z.enum(["default", "alpine"], {
|
||||||
errorMap: () => ({ message: "Type must be either 'default' or 'alpine'" }),
|
message: "Type must be either 'default' or 'alpine'",
|
||||||
}),
|
}),
|
||||||
script: z.string().min(1, "Script content cannot be empty"),
|
script: z.string().min(1, "Script content cannot be empty"),
|
||||||
resources: z.object({
|
resources: z.object({
|
||||||
@ -25,7 +25,7 @@ export const ScriptSchema = z.object({
|
|||||||
categories: z.array(z.number()),
|
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"),
|
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", "pve", "addon", "turnkey"], {
|
type: z.enum(["vm", "ct", "pve", "addon", "turnkey"], {
|
||||||
errorMap: () => ({ message: "Type must be either 'vm', 'ct', 'pve', 'addon' or 'turnkey'" }),
|
message: "Type must be either 'vm', 'ct', 'pve', 'addon' or 'turnkey'",
|
||||||
}),
|
}),
|
||||||
updateable: z.boolean(),
|
updateable: z.boolean(),
|
||||||
privileged: z.boolean(),
|
privileged: z.boolean(),
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export default function JSONGenerator() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchCategories()
|
fetchCategories()
|
||||||
.then(setCategories)
|
.then(setCategories)
|
||||||
.catch(error => console.error("Error fetching categories:", error));
|
.catch((error) => console.error("Error fetching categories:", error));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateScript = useCallback((key: keyof Script, value: Script[keyof Script]) => {
|
const updateScript = useCallback((key: keyof Script, value: Script[keyof Script]) => {
|
||||||
@ -75,14 +75,11 @@ export default function JSONGenerator() {
|
|||||||
|
|
||||||
if (updated.type === "pve") {
|
if (updated.type === "pve") {
|
||||||
scriptPath = `tools/pve/${updated.slug}.sh`;
|
scriptPath = `tools/pve/${updated.slug}.sh`;
|
||||||
}
|
} else if (updated.type === "addon") {
|
||||||
else if (updated.type === "addon") {
|
|
||||||
scriptPath = `tools/addon/${updated.slug}.sh`;
|
scriptPath = `tools/addon/${updated.slug}.sh`;
|
||||||
}
|
} else if (method.type === "alpine") {
|
||||||
else if (method.type === "alpine") {
|
|
||||||
scriptPath = `${updated.type}/alpine-${updated.slug}.sh`;
|
scriptPath = `${updated.type}/alpine-${updated.slug}.sh`;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
scriptPath = `${updated.type}/${updated.slug}.sh`;
|
scriptPath = `${updated.type}/${updated.slug}.sh`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +142,9 @@ export default function JSONGenerator() {
|
|||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
{zodErrors && (
|
{zodErrors && (
|
||||||
<div className="mt-2 space-y-1">
|
<div className="mt-2 space-y-1">
|
||||||
{zodErrors.errors.map((error, index) => (
|
{zodErrors.issues.map((error, index) => (
|
||||||
<AlertDescription key={index} className="p-1 text-red-500">
|
<AlertDescription key={index} className="p-1 text-red-500">
|
||||||
{error.path.join(".")}
|
{error.path.join(".")} -{error.message}
|
||||||
{" "}
|
|
||||||
-
|
|
||||||
{error.message}
|
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -168,31 +162,25 @@ export default function JSONGenerator() {
|
|||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<Label>
|
<Label>
|
||||||
Name
|
Name <span className="text-red-500">*</span>
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input placeholder="Example" value={script.name} onChange={e => updateScript("name", e.target.value)} />
|
<Input placeholder="Example" value={script.name} onChange={(e) => updateScript("name", e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label>
|
<Label>
|
||||||
Slug
|
Slug <span className="text-red-500">*</span>
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input placeholder="example" value={script.slug} onChange={e => updateScript("slug", e.target.value)} />
|
<Input placeholder="example" value={script.slug} onChange={(e) => updateScript("slug", e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label>
|
<Label>
|
||||||
Logo
|
Logo <span className="text-red-500">*</span>
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Full logo URL"
|
placeholder="Full logo URL"
|
||||||
value={script.logo || ""}
|
value={script.logo || ""}
|
||||||
onChange={e => updateScript("logo", e.target.value || null)}
|
onChange={(e) => updateScript("logo", e.target.value || null)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -200,19 +188,17 @@ export default function JSONGenerator() {
|
|||||||
<Input
|
<Input
|
||||||
placeholder="Path to config file"
|
placeholder="Path to config file"
|
||||||
value={script.config_path || ""}
|
value={script.config_path || ""}
|
||||||
onChange={e => updateScript("config_path", e.target.value || null)}
|
onChange={(e) => updateScript("config_path", e.target.value || null)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label>
|
<Label>
|
||||||
Description
|
Description <span className="text-red-500">*</span>
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder="Example"
|
placeholder="Example"
|
||||||
value={script.description}
|
value={script.description}
|
||||||
onChange={e => updateScript("description", e.target.value)}
|
onChange={(e) => updateScript("description", e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Categories script={script} setScript={setScript} categories={categories} />
|
<Categories script={script} setScript={setScript} categories={categories} />
|
||||||
@ -241,7 +227,7 @@ export default function JSONGenerator() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2 w-full">
|
<div className="flex flex-col gap-2 w-full">
|
||||||
<Label>Type</Label>
|
<Label>Type</Label>
|
||||||
<Select value={script.type} onValueChange={value => updateScript("type", value)}>
|
<Select value={script.type} onValueChange={(value) => updateScript("type", value)}>
|
||||||
<SelectTrigger className="flex-1">
|
<SelectTrigger className="flex-1">
|
||||||
<SelectValue placeholder="Type" />
|
<SelectValue placeholder="Type" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
@ -256,29 +242,30 @@ export default function JSONGenerator() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full flex gap-5">
|
<div className="w-full flex gap-5">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Switch checked={script.updateable} onCheckedChange={checked => updateScript("updateable", checked)} />
|
<Switch checked={script.updateable} onCheckedChange={(checked) => updateScript("updateable", checked)} />
|
||||||
<label>Updateable</label>
|
<label>Updateable</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Switch checked={script.privileged} onCheckedChange={checked => updateScript("privileged", checked)} />
|
<Switch checked={script.privileged} onCheckedChange={(checked) => updateScript("privileged", checked)} />
|
||||||
<label>Privileged</label>
|
<label>Privileged</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Switch checked={script.disable || false} onCheckedChange={checked => updateScript("disable", checked)} />
|
<Switch
|
||||||
|
checked={script.disable || false}
|
||||||
|
onCheckedChange={(checked) => updateScript("disable", checked)}
|
||||||
|
/>
|
||||||
<label>Disabled</label>
|
<label>Disabled</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{script.disable && (
|
{script.disable && (
|
||||||
<div>
|
<div>
|
||||||
<Label>
|
<Label>
|
||||||
Disable Description
|
Disable Description <span className="text-red-500">*</span>
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder="Explain why this script is disabled..."
|
placeholder="Explain why this script is disabled..."
|
||||||
value={script.disable_description || ""}
|
value={script.disable_description || ""}
|
||||||
onChange={e => updateScript("disable_description", e.target.value)}
|
onChange={(e) => updateScript("disable_description", e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -286,18 +273,18 @@ export default function JSONGenerator() {
|
|||||||
placeholder="Interface Port"
|
placeholder="Interface Port"
|
||||||
type="number"
|
type="number"
|
||||||
value={script.interface_port || ""}
|
value={script.interface_port || ""}
|
||||||
onChange={e => updateScript("interface_port", e.target.value ? Number(e.target.value) : null)}
|
onChange={(e) => updateScript("interface_port", e.target.value ? Number(e.target.value) : null)}
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input
|
<Input
|
||||||
placeholder="Website URL"
|
placeholder="Website URL"
|
||||||
value={script.website || ""}
|
value={script.website || ""}
|
||||||
onChange={e => updateScript("website", e.target.value || null)}
|
onChange={(e) => updateScript("website", e.target.value || null)}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Documentation URL"
|
placeholder="Documentation URL"
|
||||||
value={script.documentation || ""}
|
value={script.documentation || ""}
|
||||||
onChange={e => updateScript("documentation", e.target.value || null)}
|
onChange={(e) => updateScript("documentation", e.target.value || null)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<InstallMethod script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
|
<InstallMethod script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
|
||||||
@ -305,20 +292,22 @@ export default function JSONGenerator() {
|
|||||||
<Input
|
<Input
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
value={script.default_credentials.username || ""}
|
value={script.default_credentials.username || ""}
|
||||||
onChange={e =>
|
onChange={(e) =>
|
||||||
updateScript("default_credentials", {
|
updateScript("default_credentials", {
|
||||||
...script.default_credentials,
|
...script.default_credentials,
|
||||||
username: e.target.value || null,
|
username: e.target.value || null,
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
value={script.default_credentials.password || ""}
|
value={script.default_credentials.password || ""}
|
||||||
onChange={e =>
|
onChange={(e) =>
|
||||||
updateScript("default_credentials", {
|
updateScript("default_credentials", {
|
||||||
...script.default_credentials,
|
...script.default_credentials,
|
||||||
password: e.target.value || null,
|
password: e.target.value || null,
|
||||||
})}
|
})
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Note script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
|
<Note script={script} setScript={setScript} setIsValid={setIsValid} setZodErrors={setZodErrors} />
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,50 +1,45 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import * as RechartsPrimitive from "recharts"
|
import * as RechartsPrimitive from "recharts";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
// Format: { THEME_NAME: CSS_SELECTOR }
|
// Format: { THEME_NAME: CSS_SELECTOR }
|
||||||
const THEMES = { light: "", dark: ".dark" } as const
|
const THEMES = { light: "", dark: ".dark" } as const;
|
||||||
|
|
||||||
export type ChartConfig = {
|
export type ChartConfig = {
|
||||||
[k in string]: {
|
[k in string]: {
|
||||||
label?: React.ReactNode
|
label?: React.ReactNode;
|
||||||
icon?: React.ComponentType
|
icon?: React.ComponentType;
|
||||||
} & (
|
} & ({ color?: string; theme?: never } | { color?: never; theme: Record<keyof typeof THEMES, string> });
|
||||||
| { color?: string; theme?: never }
|
};
|
||||||
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChartContextProps = {
|
type ChartContextProps = {
|
||||||
config: ChartConfig
|
config: ChartConfig;
|
||||||
}
|
};
|
||||||
|
|
||||||
const ChartContext = React.createContext<ChartContextProps | null>(null)
|
const ChartContext = React.createContext<ChartContextProps | null>(null);
|
||||||
|
|
||||||
function useChart() {
|
function useChart() {
|
||||||
const context = React.useContext(ChartContext)
|
const context = React.useContext(ChartContext);
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error("useChart must be used within a <ChartContainer />")
|
throw new Error("useChart must be used within a <ChartContainer />");
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChartContainer = React.forwardRef<
|
const ChartContainer = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
React.ComponentProps<"div"> & {
|
React.ComponentProps<"div"> & {
|
||||||
config: ChartConfig
|
config: ChartConfig;
|
||||||
children: React.ComponentProps<
|
children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>["children"];
|
||||||
typeof RechartsPrimitive.ResponsiveContainer
|
|
||||||
>["children"]
|
|
||||||
}
|
}
|
||||||
>(({ id, className, children, config, ...props }, ref) => {
|
>(({ id, className, children, config, ...props }, ref) => {
|
||||||
const uniqueId = React.useId()
|
const uniqueId = React.useId();
|
||||||
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
|
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChartContext.Provider value={{ config }}>
|
<ChartContext.Provider value={{ config }}>
|
||||||
@ -58,22 +53,18 @@ const ChartContainer = React.forwardRef<
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChartStyle id={chartId} config={config} />
|
<ChartStyle id={chartId} config={config} />
|
||||||
<RechartsPrimitive.ResponsiveContainer>
|
<RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>
|
||||||
{children}
|
|
||||||
</RechartsPrimitive.ResponsiveContainer>
|
|
||||||
</div>
|
</div>
|
||||||
</ChartContext.Provider>
|
</ChartContext.Provider>
|
||||||
)
|
);
|
||||||
})
|
});
|
||||||
ChartContainer.displayName = "Chart"
|
ChartContainer.displayName = "Chart";
|
||||||
|
|
||||||
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
||||||
const colorConfig = Object.entries(config).filter(
|
const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color);
|
||||||
([, config]) => config.theme || config.color
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!colorConfig.length) {
|
if (!colorConfig.length) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -85,10 +76,8 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|||||||
${prefix} [data-chart=${id}] {
|
${prefix} [data-chart=${id}] {
|
||||||
${colorConfig
|
${colorConfig
|
||||||
.map(([key, itemConfig]) => {
|
.map(([key, itemConfig]) => {
|
||||||
const color =
|
const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color;
|
||||||
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
|
return color ? ` --color-${key}: ${color};` : null;
|
||||||
itemConfig.color
|
|
||||||
return color ? ` --color-${key}: ${color};` : null
|
|
||||||
})
|
})
|
||||||
.join("\n")}
|
.join("\n")}
|
||||||
}
|
}
|
||||||
@ -97,20 +86,37 @@ ${colorConfig
|
|||||||
.join("\n"),
|
.join("\n"),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const ChartTooltip = RechartsPrimitive.Tooltip
|
const ChartTooltip = RechartsPrimitive.Tooltip;
|
||||||
|
|
||||||
|
type TooltipPayloadItem = {
|
||||||
|
value?: string | number;
|
||||||
|
name?: string;
|
||||||
|
dataKey?: string | number;
|
||||||
|
payload?: Record<string, unknown>;
|
||||||
|
color?: string;
|
||||||
|
fill?: string;
|
||||||
|
type?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const ChartTooltipContent = React.forwardRef<
|
const ChartTooltipContent = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
Omit<React.ComponentProps<typeof RechartsPrimitive.Tooltip>, "content"> &
|
||||||
React.ComponentProps<"div"> & {
|
React.ComponentProps<"div"> & {
|
||||||
hideLabel?: boolean
|
active?: boolean;
|
||||||
hideIndicator?: boolean
|
payload?: TooltipPayloadItem[];
|
||||||
indicator?: "line" | "dot" | "dashed"
|
hideLabel?: boolean;
|
||||||
nameKey?: string
|
hideIndicator?: boolean;
|
||||||
labelKey?: string
|
indicator?: "line" | "dot" | "dashed";
|
||||||
|
nameKey?: string;
|
||||||
|
labelKey?: string;
|
||||||
|
label?: string;
|
||||||
|
labelFormatter?: (value: any, payload: TooltipPayloadItem[]) => React.ReactNode;
|
||||||
|
labelClassName?: string;
|
||||||
|
formatter?: (value: any, name: string, item: TooltipPayloadItem, index: number, payload: any) => React.ReactNode;
|
||||||
|
color?: string;
|
||||||
}
|
}
|
||||||
>(
|
>(
|
||||||
(
|
(
|
||||||
@ -131,49 +137,37 @@ const ChartTooltipContent = React.forwardRef<
|
|||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const { config } = useChart()
|
const { config } = useChart();
|
||||||
|
|
||||||
const tooltipLabel = React.useMemo(() => {
|
const tooltipLabel = React.useMemo(() => {
|
||||||
if (hideLabel || !payload?.length) {
|
if (hideLabel || !payload?.length) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const [item] = payload
|
const [item] = payload;
|
||||||
const key = `${labelKey || item?.dataKey || item?.name || "value"}`
|
const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
||||||
const value =
|
const value =
|
||||||
!labelKey && typeof label === "string"
|
!labelKey && typeof label === "string"
|
||||||
? config[label as keyof typeof config]?.label || label
|
? config[label as keyof typeof config]?.label || label
|
||||||
: itemConfig?.label
|
: itemConfig?.label;
|
||||||
|
|
||||||
if (labelFormatter) {
|
if (labelFormatter) {
|
||||||
return (
|
return <div className={cn("font-medium", labelClassName)}>{labelFormatter(value, payload)}</div>;
|
||||||
<div className={cn("font-medium", labelClassName)}>
|
|
||||||
{labelFormatter(value, payload)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className={cn("font-medium", labelClassName)}>{value}</div>
|
return <div className={cn("font-medium", labelClassName)}>{value}</div>;
|
||||||
}, [
|
}, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
|
||||||
label,
|
|
||||||
labelFormatter,
|
|
||||||
payload,
|
|
||||||
hideLabel,
|
|
||||||
labelClassName,
|
|
||||||
config,
|
|
||||||
labelKey,
|
|
||||||
])
|
|
||||||
|
|
||||||
if (!active || !payload?.length) {
|
if (!active || !payload?.length) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nestLabel = payload.length === 1 && indicator !== "dot"
|
const nestLabel = payload.length === 1 && indicator !== "dot";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -188,9 +182,9 @@ const ChartTooltipContent = React.forwardRef<
|
|||||||
{payload
|
{payload
|
||||||
.filter((item) => item.type !== "none")
|
.filter((item) => item.type !== "none")
|
||||||
.map((item, index) => {
|
.map((item, index) => {
|
||||||
const key = `${nameKey || item.name || item.dataKey || "value"}`
|
const key = `${nameKey || item.name || item.dataKey || "value"}`;
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
||||||
const indicatorColor = color || item.payload.fill || item.color
|
const indicatorColor = color || item.payload?.fill || item.color;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -209,16 +203,12 @@ const ChartTooltipContent = React.forwardRef<
|
|||||||
) : (
|
) : (
|
||||||
!hideIndicator && (
|
!hideIndicator && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn("shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]", {
|
||||||
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
|
|
||||||
{
|
|
||||||
"h-2.5 w-2.5": indicator === "dot",
|
"h-2.5 w-2.5": indicator === "dot",
|
||||||
"w-1": indicator === "line",
|
"w-1": indicator === "line",
|
||||||
"w-0 border-[1.5px] border-dashed bg-transparent":
|
"w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
|
||||||
indicator === "dashed",
|
|
||||||
"my-0.5": nestLabel && indicator === "dashed",
|
"my-0.5": nestLabel && indicator === "dashed",
|
||||||
}
|
})}
|
||||||
)}
|
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"--color-bg": indicatorColor,
|
"--color-bg": indicatorColor,
|
||||||
@ -236,9 +226,7 @@ const ChartTooltipContent = React.forwardRef<
|
|||||||
>
|
>
|
||||||
<div className="grid gap-1.5">
|
<div className="grid gap-1.5">
|
||||||
{nestLabel ? tooltipLabel : null}
|
{nestLabel ? tooltipLabel : null}
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">{itemConfig?.label || item.name}</span>
|
||||||
{itemConfig?.label || item.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{item.value && (
|
{item.value && (
|
||||||
<span className="font-mono font-medium tabular-nums text-foreground">
|
<span className="font-mono font-medium tabular-nums text-foreground">
|
||||||
@ -249,56 +237,54 @@ const ChartTooltipContent = React.forwardRef<
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
ChartTooltipContent.displayName = "ChartTooltip"
|
ChartTooltipContent.displayName = "ChartTooltip";
|
||||||
|
|
||||||
const ChartLegend = RechartsPrimitive.Legend
|
const ChartLegend = RechartsPrimitive.Legend;
|
||||||
|
|
||||||
|
type LegendPayloadItem = {
|
||||||
|
value?: string;
|
||||||
|
type?: string;
|
||||||
|
dataKey?: string | number;
|
||||||
|
color?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const ChartLegendContent = React.forwardRef<
|
const ChartLegendContent = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
React.ComponentProps<"div"> &
|
React.ComponentProps<"div"> & {
|
||||||
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
payload?: LegendPayloadItem[];
|
||||||
hideIcon?: boolean
|
verticalAlign?: "top" | "bottom";
|
||||||
nameKey?: string
|
hideIcon?: boolean;
|
||||||
|
nameKey?: string;
|
||||||
}
|
}
|
||||||
>(
|
>(({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => {
|
||||||
(
|
const { config } = useChart();
|
||||||
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const { config } = useChart()
|
|
||||||
|
|
||||||
if (!payload?.length) {
|
if (!payload?.length) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn("flex items-center justify-center gap-4", verticalAlign === "top" ? "pb-3" : "pt-3", className)}
|
||||||
"flex items-center justify-center gap-4",
|
|
||||||
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{payload
|
{payload
|
||||||
.filter((item) => item.type !== "none")
|
.filter((item) => item.type !== "none")
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
const key = `${nameKey || item.dataKey || "value"}`
|
const key = `${nameKey || item.dataKey || "value"}`;
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={item.value}
|
key={item.value}
|
||||||
className={cn(
|
className={cn("flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground")}
|
||||||
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{itemConfig?.icon && !hideIcon ? (
|
{itemConfig?.icon && !hideIcon ? (
|
||||||
<itemConfig.icon />
|
<itemConfig.icon />
|
||||||
@ -312,58 +298,37 @@ const ChartLegendContent = React.forwardRef<
|
|||||||
)}
|
)}
|
||||||
{itemConfig?.label}
|
{itemConfig?.label}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
});
|
||||||
)
|
ChartLegendContent.displayName = "ChartLegend";
|
||||||
ChartLegendContent.displayName = "ChartLegend"
|
|
||||||
|
|
||||||
// Helper to extract item config from a payload.
|
// Helper to extract item config from a payload.
|
||||||
function getPayloadConfigFromPayload(
|
function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {
|
||||||
config: ChartConfig,
|
|
||||||
payload: unknown,
|
|
||||||
key: string
|
|
||||||
) {
|
|
||||||
if (typeof payload !== "object" || payload === null) {
|
if (typeof payload !== "object" || payload === null) {
|
||||||
return undefined
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const payloadPayload =
|
const payloadPayload =
|
||||||
"payload" in payload &&
|
"payload" in payload && typeof payload.payload === "object" && payload.payload !== null
|
||||||
typeof payload.payload === "object" &&
|
|
||||||
payload.payload !== null
|
|
||||||
? payload.payload
|
? payload.payload
|
||||||
: undefined
|
: undefined;
|
||||||
|
|
||||||
let configLabelKey: string = key
|
let configLabelKey: string = key;
|
||||||
|
|
||||||
if (
|
if (key in payload && typeof payload[key as keyof typeof payload] === "string") {
|
||||||
key in payload &&
|
configLabelKey = payload[key as keyof typeof payload] as string;
|
||||||
typeof payload[key as keyof typeof payload] === "string"
|
|
||||||
) {
|
|
||||||
configLabelKey = payload[key as keyof typeof payload] as string
|
|
||||||
} else if (
|
} else if (
|
||||||
payloadPayload &&
|
payloadPayload &&
|
||||||
key in payloadPayload &&
|
key in payloadPayload &&
|
||||||
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
|
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
|
||||||
) {
|
) {
|
||||||
configLabelKey = payloadPayload[
|
configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string;
|
||||||
key as keyof typeof payloadPayload
|
|
||||||
] as string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return configLabelKey in config
|
return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config];
|
||||||
? config[configLabelKey]
|
|
||||||
: config[key as keyof typeof config]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle };
|
||||||
ChartContainer,
|
|
||||||
ChartTooltip,
|
|
||||||
ChartTooltipContent,
|
|
||||||
ChartLegend,
|
|
||||||
ChartLegendContent,
|
|
||||||
ChartStyle,
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
|
||||||
import { defineConfig } from "vitest/config";
|
|
||||||
import react from "@vitejs/plugin-react";
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [tsconfigPaths(), react()],
|
|
||||||
test: {
|
|
||||||
environment: "jsdom",
|
|
||||||
setupFiles: ["src/__tests__/setupTests.ts"],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@ -17,7 +17,8 @@ msg_info "Installing Dependencies"
|
|||||||
$STD apt install -y nginx
|
$STD apt install -y nginx
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
PHP_VERSION="8.3" PHP_MODULE="common,ctype,fileinfo,mysql,cli,tokenizer,dom,redis,session,openssl" PHP_FPM="YES" setup_php
|
PHP_VERSION="8.4"
|
||||||
|
PHP_MODULE="common,ctype,fileinfo,mysql,tokenizer,dom,redis" PHP_FPM="YES" setup_php
|
||||||
setup_composer
|
setup_composer
|
||||||
setup_mariadb
|
setup_mariadb
|
||||||
MARIADB_DB_NAME="2fauth_db" MARIADB_DB_USER="2fauth" setup_mariadb_db
|
MARIADB_DB_NAME="2fauth_db" MARIADB_DB_USER="2fauth" setup_mariadb_db
|
||||||
@ -65,7 +66,7 @@ server {
|
|||||||
error_page 404 /index.php;
|
error_page 404 /index.php;
|
||||||
|
|
||||||
location ~ \.php\$ {
|
location ~ \.php\$ {
|
||||||
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
|
fastcgi_pass unix:/var/run/php/php${PHP_VERSION}-fpm.sock;
|
||||||
fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
|
||||||
include fastcgi_params;
|
include fastcgi_params;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ catch_errors
|
|||||||
setting_up_container
|
setting_up_container
|
||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
setup_hwaccel
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt install -y \
|
$STD apt install -y \
|
||||||
|
|||||||
@ -29,19 +29,7 @@ if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
|||||||
exit 10
|
exit 10
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$CTTYPE" == "0" ]]; then
|
setup_hwaccel
|
||||||
msg_info "Setting Up Hardware Acceleration"
|
|
||||||
$STD apt-get -y install \
|
|
||||||
va-driver-all \
|
|
||||||
ocl-icd-libopencl1 \
|
|
||||||
intel-opencl-icd
|
|
||||||
chgrp video /dev/dri
|
|
||||||
chmod 755 /dev/dri
|
|
||||||
chmod 660 /dev/dri/*
|
|
||||||
$STD adduser $(id -u -n) video
|
|
||||||
$STD adduser $(id -u -n) render
|
|
||||||
msg_ok "Set Up Hardware Acceleration"
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Installing Channels DVR Server (Patience)"
|
msg_info "Installing Channels DVR Server (Patience)"
|
||||||
cd /opt
|
cd /opt
|
||||||
|
|||||||
@ -12,6 +12,7 @@ catch_errors
|
|||||||
setting_up_container
|
setting_up_container
|
||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
setup_hwaccel
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "${TAB3}Choose the GPU type for ComfyUI:"
|
echo "${TAB3}Choose the GPU type for ComfyUI:"
|
||||||
|
|||||||
@ -12,6 +12,7 @@ catch_errors
|
|||||||
setting_up_container
|
setting_up_container
|
||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
setup_hwaccel
|
||||||
|
|
||||||
setup_imagemagick
|
setup_imagemagick
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,8 @@ fetch_and_deploy_gh_release "discopanel" "nickheyer/discopanel" "tarball" "lates
|
|||||||
setup_docker
|
setup_docker
|
||||||
|
|
||||||
msg_info "Setting up DiscoPanel"
|
msg_info "Setting up DiscoPanel"
|
||||||
|
cd /opt/discopanel
|
||||||
|
$STD make gen
|
||||||
cd /opt/discopanel/web/discopanel
|
cd /opt/discopanel/web/discopanel
|
||||||
$STD npm install
|
$STD npm install
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
|
|||||||
@ -12,6 +12,7 @@ catch_errors
|
|||||||
setting_up_container
|
setting_up_container
|
||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
setup_hwaccel
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt install -y \
|
$STD apt install -y \
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user