mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-11-24 06:25:15 +00:00
Compare commits
1 Commits
2025-11-23
...
pr-update-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03c40fad1c |
12
.github/ISSUE_TEMPLATE/bug_report.yml
generated
vendored
12
.github/ISSUE_TEMPLATE/bug_report.yml
generated
vendored
@@ -22,18 +22,6 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: verbose_run
|
|
||||||
attributes:
|
|
||||||
label: 🔎 Did you run the script with verbose mode enabled?
|
|
||||||
description: "Required for debugging any script issue. A verbose log is mandatory."
|
|
||||||
options:
|
|
||||||
- ""
|
|
||||||
- "Yes, verbose mode was enabled and the output is included below"
|
|
||||||
- "No (this issue will likely be closed automatically)"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
- type: input
|
||||||
id: script_name
|
id: script_name
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
129
CHANGELOG.md
129
CHANGELOG.md
@@ -10,137 +10,16 @@
|
|||||||
> [!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-11-24
|
|
||||||
|
|
||||||
## 2025-11-23
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: remove journal log rotation [@MickLesk](https://github.com/MickLesk) ([#9392](https://github.com/community-scripts/ProxmoxVE/pull/9392))
|
|
||||||
- [LibreNMS] Correcting mariadb sed string for Debian 13 default in install/librenms-install.sh, website config for Debian 13 #9369 [@htmlspinnr](https://github.com/htmlspinnr) ([#9370](https://github.com/community-scripts/ProxmoxVE/pull/9370))
|
|
||||||
- fix: Snipe-IT update check failure [@ruanmed](https://github.com/ruanmed) ([#9371](https://github.com/community-scripts/ProxmoxVE/pull/9371))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- PVE Kernel Clean: Add info about currently running kernel [@tremor021](https://github.com/tremor021) ([#9388](https://github.com/community-scripts/ProxmoxVE/pull/9388))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Update glpi-install.sh to remove install.php [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9378](https://github.com/community-scripts/ProxmoxVE/pull/9378))
|
|
||||||
|
|
||||||
### 🌐 Website
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- fix: enhance back navigation in NotFoundPage component and remove unused deps [@BramSuurdje](https://github.com/BramSuurdje) ([#9341](https://github.com/community-scripts/ProxmoxVE/pull/9341))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- feat(frontend): add script disable functionality with visual indicators [@AlphaLawless](https://github.com/AlphaLawless) ([#9374](https://github.com/community-scripts/ProxmoxVE/pull/9374))
|
|
||||||
|
|
||||||
## 2025-11-22
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- Upgopher ([#9360](https://github.com/community-scripts/ProxmoxVE/pull/9360))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- Expand support to Proxmox VE 9.1 in VM scripts [@MickLesk](https://github.com/MickLesk) ([#9351](https://github.com/community-scripts/ProxmoxVE/pull/9351))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- fix: Snipe-IT install and update failure due to new repository url [@ruanmed](https://github.com/ruanmed) ([#9362](https://github.com/community-scripts/ProxmoxVE/pull/9362))
|
|
||||||
- glpi - allow migration of existing databases [@moodyblue](https://github.com/moodyblue) ([#9353](https://github.com/community-scripts/ProxmoxVE/pull/9353))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Refactor cleanup steps to use cleanup_lxc function (install/ Folder) [@MickLesk](https://github.com/MickLesk) ([#9354](https://github.com/community-scripts/ProxmoxVE/pull/9354))
|
|
||||||
- Remove redundant cleanup steps from update scripts (ct/ Folder) [@MickLesk](https://github.com/MickLesk) ([#9359](https://github.com/community-scripts/ProxmoxVE/pull/9359))
|
|
||||||
|
|
||||||
### 🌐 Website
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Refactor /data page [@BramSuurdje](https://github.com/BramSuurdje) ([#9343](https://github.com/community-scripts/ProxmoxVE/pull/9343))
|
|
||||||
|
|
||||||
## 2025-11-21
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- plex: prevent [] syntax issue [@MickLesk](https://github.com/MickLesk) ([#9318](https://github.com/community-scripts/ProxmoxVE/pull/9318))
|
|
||||||
- fix: karakeep strip "v" from release version [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9324](https://github.com/community-scripts/ProxmoxVE/pull/9324))
|
|
||||||
- NetVisor: fix grep in update [@vhsdream](https://github.com/vhsdream) ([#9334](https://github.com/community-scripts/ProxmoxVE/pull/9334))
|
|
||||||
- Immich: pin correct version [@vhsdream](https://github.com/vhsdream) ([#9332](https://github.com/community-scripts/ProxmoxVE/pull/9332))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- Refactor IPv6 disable logic and add 'disable' option [@MickLesk](https://github.com/MickLesk) ([#9326](https://github.com/community-scripts/ProxmoxVE/pull/9326))
|
|
||||||
|
|
||||||
## 2025-11-20
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- core: change 'uv cache clear' to 'uv cache clean' [@MickLesk](https://github.com/MickLesk) ([#9299](https://github.com/community-scripts/ProxmoxVE/pull/9299))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- Immich v2.3.1: OpenVINO tuning, OCR fixes, Maintenance mode, workflows/plugin framework [@vhsdream](https://github.com/vhsdream) ([#9310](https://github.com/community-scripts/ProxmoxVE/pull/9310))
|
|
||||||
- kasm: add: update [@CrazyWolf13](https://github.com/CrazyWolf13) ([#9253](https://github.com/community-scripts/ProxmoxVE/pull/9253))
|
|
||||||
- tools/pve: expand PVE support to 9.0–9.1 (post-install & netdata) [@MickLesk](https://github.com/MickLesk) ([#9298](https://github.com/community-scripts/ProxmoxVE/pull/9298))
|
|
||||||
|
|
||||||
- #### 💥 Breaking Changes
|
|
||||||
|
|
||||||
- Omada - AVX-only support [@MickLesk](https://github.com/MickLesk) ([#9295](https://github.com/community-scripts/ProxmoxVE/pull/9295))
|
|
||||||
|
|
||||||
## 2025-11-19
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- HotFix: Fix NetVisor env var [@vhsdream](https://github.com/vhsdream) ([#9286](https://github.com/community-scripts/ProxmoxVE/pull/9286))
|
|
||||||
- Jotty: reduce RAM requirement [@vhsdream](https://github.com/vhsdream) ([#9272](https://github.com/community-scripts/ProxmoxVE/pull/9272))
|
|
||||||
- Nginx Proxy Manager: Pin version to v2.13.4 [@tremor021](https://github.com/tremor021) ([#9259](https://github.com/community-scripts/ProxmoxVE/pull/9259))
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- PVE 9.1 version support [@MickLesk](https://github.com/MickLesk) ([#9280](https://github.com/community-scripts/ProxmoxVE/pull/9280))
|
|
||||||
- force disable IPv6 if IPV6_METHOD = none [@MickLesk](https://github.com/MickLesk) ([#9277](https://github.com/community-scripts/ProxmoxVE/pull/9277))
|
|
||||||
|
|
||||||
- #### 💥 Breaking Changes
|
|
||||||
|
|
||||||
- NetVisor: v0.10.0 fixes [@vhsdream](https://github.com/vhsdream) ([#9255](https://github.com/community-scripts/ProxmoxVE/pull/9255))
|
|
||||||
|
|
||||||
## 2025-11-18
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- librenms: Fix password to short [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#9236](https://github.com/community-scripts/ProxmoxVE/pull/9236))
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Huntarr: Downgrade Python to 3.12 [@MickLesk](https://github.com/MickLesk) ([#9246](https://github.com/community-scripts/ProxmoxVE/pull/9246))
|
|
||||||
- kasm: fix release fetching [@MickLesk](https://github.com/MickLesk) ([#9244](https://github.com/community-scripts/ProxmoxVE/pull/9244))
|
|
||||||
|
|
||||||
## 2025-11-17
|
## 2025-11-17
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
|
|
||||||
- Passbolt ([#9226](https://github.com/community-scripts/ProxmoxVE/pull/9226))
|
- Domain-Locker ([#9214](https://github.com/community-scripts/ProxmoxVE/pull/9214))
|
||||||
- Domain-Locker ([#9214](https://github.com/community-scripts/ProxmoxVE/pull/9214))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
- Domain Monitor: Fix encryption key length in install script [@tremor021](https://github.com/tremor021) ([#9239](https://github.com/community-scripts/ProxmoxVE/pull/9239))
|
|
||||||
- NetVisor: add build deps, increase RAM [@vhsdream](https://github.com/vhsdream) ([#9205](https://github.com/community-scripts/ProxmoxVE/pull/9205))
|
- NetVisor: add build deps, increase RAM [@vhsdream](https://github.com/vhsdream) ([#9205](https://github.com/community-scripts/ProxmoxVE/pull/9205))
|
||||||
- fix: restart apache2 after installing zabbix config [@AlphaLawless](https://github.com/AlphaLawless) ([#9206](https://github.com/community-scripts/ProxmoxVE/pull/9206))
|
- fix: restart apache2 after installing zabbix config [@AlphaLawless](https://github.com/AlphaLawless) ([#9206](https://github.com/community-scripts/ProxmoxVE/pull/9206))
|
||||||
|
|
||||||
@@ -152,12 +31,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
- Refactor: paperless-ngx (Breaking Change Inside) [@MickLesk](https://github.com/MickLesk) ([#9223](https://github.com/community-scripts/ProxmoxVE/pull/9223))
|
- Refactor: paperless-ngx (Breaking Change Inside) [@MickLesk](https://github.com/MickLesk) ([#9223](https://github.com/community-scripts/ProxmoxVE/pull/9223))
|
||||||
|
|
||||||
### 🧰 Maintenance
|
|
||||||
|
|
||||||
- #### 📂 Github
|
|
||||||
|
|
||||||
- github: add verbose mode check to bug report template [@MickLesk](https://github.com/MickLesk) ([#9234](https://github.com/community-scripts/ProxmoxVE/pull/9234))
|
|
||||||
|
|
||||||
## 2025-11-16
|
## 2025-11-16
|
||||||
|
|
||||||
### 🆕 New Scripts
|
### 🆕 New Scripts
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module proxmox-api
|
module proxmox-api
|
||||||
|
|
||||||
go 1.24.0
|
go 1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
@@ -17,7 +17,7 @@ require (
|
|||||||
github.com/xdg-go/scram v1.1.2 // indirect
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
golang.org/x/crypto v0.45.0 // indirect
|
golang.org/x/crypto v0.35.0 // indirect
|
||||||
golang.org/x/sync v0.18.0 // indirect
|
golang.org/x/sync v0.11.0 // indirect
|
||||||
golang.org/x/text v0.31.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
12
api/go.sum
12
api/go.sum
@@ -27,16 +27,16 @@ go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793Sqyh
|
|||||||
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
|
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||||
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
|
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -48,8 +48,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
|||||||
@@ -57,6 +57,15 @@ function update_script() {
|
|||||||
$STD composer install --no-dev --prefer-dist
|
$STD composer install --no-dev --prefer-dist
|
||||||
php artisan 2fauth:install
|
php artisan 2fauth:install
|
||||||
$STD systemctl restart nginx
|
$STD systemctl restart nginx
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
if dpkg -l | grep -q 'php8.2'; then
|
||||||
|
$STD apt remove --purge -y php8.2*
|
||||||
|
fi
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ function update_script() {
|
|||||||
cd /opt/adventurelog/frontend || exit
|
cd /opt/adventurelog/frontend || exit
|
||||||
$STD pnpm i
|
$STD pnpm i
|
||||||
$STD pnpm build
|
$STD pnpm build
|
||||||
rm -rf /opt/adventurelog-backup
|
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
@@ -70,6 +69,10 @@ function update_script() {
|
|||||||
systemctl start adventurelog-backend
|
systemctl start adventurelog-backend
|
||||||
systemctl start adventurelog-frontend
|
systemctl start adventurelog-frontend
|
||||||
msg_ok "Services Started"
|
msg_ok "Services Started"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/adventurelog-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -38,13 +38,15 @@ function update_script() {
|
|||||||
curl -fsSL -o tika-server-standard-${RELEASE}.jar "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar"
|
curl -fsSL -o tika-server-standard-${RELEASE}.jar "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar"
|
||||||
mv --force tika-server-standard.jar tika-server-standard-prev-version.jar
|
mv --force tika-server-standard.jar tika-server-standard-prev-version.jar
|
||||||
mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar
|
mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar
|
||||||
rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to v${RELEASE}"
|
msg_ok "Updated ${APP} to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start apache-tika
|
systemctl start apache-tika
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -31,11 +31,15 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "authelia" "authelia/authelia"; then
|
if check_for_gh_release "authelia" "authelia/authelia"; then
|
||||||
$STD apt update
|
$STD apt-get update
|
||||||
$STD apt -y upgrade
|
$STD apt-get -y upgrade
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "authelia" "authelia/authelia" "binary"
|
fetch_and_deploy_gh_release "authelia" "authelia/authelia" "binary"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
$STD apt-get -y autoremove
|
||||||
|
$STD apt-get -y autoclean
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -39,13 +39,16 @@ function update_script() {
|
|||||||
curl -fsSL "https://github.com/garethgeorge/backrest/releases/download/v${RELEASE}/backrest_Linux_x86_64.tar.gz" -o "$temp_file"
|
curl -fsSL "https://github.com/garethgeorge/backrest/releases/download/v${RELEASE}/backrest_Linux_x86_64.tar.gz" -o "$temp_file"
|
||||||
tar xzf $temp_file -C /opt/backrest/bin
|
tar xzf $temp_file -C /opt/backrest/bin
|
||||||
chmod +x /opt/backrest/bin/backrest
|
chmod +x /opt/backrest/bin/backrest
|
||||||
rm -f "$temp_file"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to ${RELEASE}"
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start backrest
|
systemctl start backrest
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -f "$temp_file"
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -47,12 +47,15 @@ function update_script() {
|
|||||||
chmod -R 755 /opt/baikal/
|
chmod -R 755 /opt/baikal/
|
||||||
cd /opt/baikal
|
cd /opt/baikal
|
||||||
$STD composer install
|
$STD composer install
|
||||||
rm -rf /opt/baikal-backup
|
|
||||||
msg_ok "Configured Baikal"
|
msg_ok "Configured Baikal"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start apache2
|
systemctl start apache2
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/baikal-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -54,12 +54,15 @@ function update_script() {
|
|||||||
$STD php artisan route:cache
|
$STD php artisan route:cache
|
||||||
$STD php artisan event:cache
|
$STD php artisan event:cache
|
||||||
chown -R www-data:www-data /opt/bar-assistant
|
chown -R www-data:www-data /opt/bar-assistant
|
||||||
rm -rf /opt/bar-assistant-backup
|
|
||||||
msg_ok "Updated Bar-Assistant"
|
msg_ok "Updated Bar-Assistant"
|
||||||
|
|
||||||
msg_info "Starting nginx"
|
msg_info "Starting nginx"
|
||||||
systemctl start nginx
|
systemctl start nginx
|
||||||
msg_ok "Started nginx"
|
msg_ok "Started nginx"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/bar-assistant-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "vue-salt-rim" "karlomikus/vue-salt-rim"; then
|
if check_for_gh_release "vue-salt-rim" "karlomikus/vue-salt-rim"; then
|
||||||
@@ -78,12 +81,15 @@ function update_script() {
|
|||||||
cd /opt/vue-salt-rim
|
cd /opt/vue-salt-rim
|
||||||
$STD npm install
|
$STD npm install
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
rm -rf /opt/vue-salt-rim-backup
|
|
||||||
msg_ok "Updated Vue Salt Rim"
|
msg_ok "Updated Vue Salt Rim"
|
||||||
|
|
||||||
msg_info "Starting nginx"
|
msg_info "Starting nginx"
|
||||||
systemctl start nginx
|
systemctl start nginx
|
||||||
msg_ok "Started nginx"
|
msg_ok "Started nginx"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/vue-salt-rim-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "meilisearch" "meilisearch/meilisearch"; then
|
if check_for_gh_release "meilisearch" "meilisearch/meilisearch"; then
|
||||||
|
|||||||
@@ -57,12 +57,15 @@ function update_script() {
|
|||||||
chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage
|
chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage
|
||||||
chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads
|
chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads
|
||||||
chmod -R 640 /opt/bookstack/.env
|
chmod -R 640 /opt/bookstack/.env
|
||||||
rm -rf /opt/bookstack-backup
|
|
||||||
msg_ok "Configured BookStack"
|
msg_ok "Configured BookStack"
|
||||||
|
|
||||||
msg_info "Starting Apache2"
|
msg_info "Starting Apache2"
|
||||||
systemctl start apache2
|
systemctl start apache2
|
||||||
msg_ok "Started Apache2"
|
msg_ok "Started Apache2"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/bookstack-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
$STD uv run python manage.py migrate --noinput
|
$STD uv run python manage.py migrate --noinput
|
||||||
$STD uv run python manage.py collectstatic --noinput
|
$STD uv run python manage.py collectstatic --noinput
|
||||||
rm -f /tmp/dispatcharr_db_*.sql
|
|
||||||
msg_ok "Migrations Complete"
|
msg_ok "Migrations Complete"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
@@ -118,6 +117,10 @@ function update_script() {
|
|||||||
systemctl start dispatcharr-celerybeat
|
systemctl start dispatcharr-celerybeat
|
||||||
systemctl start dispatcharr-daphne
|
systemctl start dispatcharr-daphne
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -f /tmp/dispatcharr_db_*.sql
|
||||||
|
msg_ok "Cleanup completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ function update_script() {
|
|||||||
portainer/agent
|
portainer/agent
|
||||||
msg_ok "Updated Portainer Agent"
|
msg_ok "Updated Portainer Agent"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD apt-get -y autoremove
|
||||||
|
$STD apt-get -y autoclean
|
||||||
|
msg_ok "Cleanup complete"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,13 +50,16 @@ function update_script() {
|
|||||||
$STD turbo run build --filter=@documenso/remix
|
$STD turbo run build --filter=@documenso/remix
|
||||||
$STD npm run prisma:migrate-deploy
|
$STD npm run prisma:migrate-deploy
|
||||||
$STD turbo daemon stop
|
$STD turbo daemon stop
|
||||||
rm -rf /opt/v${RELEASE}.zip
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start documenso
|
systemctl start documenso
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/v${RELEASE}.zip
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -47,13 +47,16 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Installing EMQX"
|
msg_info "Installing EMQX"
|
||||||
$STD apt-get install -y "$DEB_FILE"
|
$STD apt-get install -y "$DEB_FILE"
|
||||||
rm -f "$DEB_FILE"
|
|
||||||
echo "$RELEASE" >~/.emqx
|
|
||||||
msg_ok "Installed EMQX v${RELEASE}"
|
msg_ok "Installed EMQX v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting EMQX"
|
msg_info "Starting EMQX"
|
||||||
systemctl start emqx
|
systemctl start emqx
|
||||||
|
echo "$RELEASE" >~/.emqx
|
||||||
msg_ok "Started EMQX"
|
msg_ok "Started EMQX"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f "$DEB_FILE"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. EMQX is already at v${RELEASE}"
|
msg_ok "No update required. EMQX is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -48,13 +48,16 @@ function update_script() {
|
|||||||
temp_file=$(mktemp)
|
temp_file=$(mktemp)
|
||||||
curl -fsSL https://fileflows.com/downloads/zip -o "$temp_file"
|
curl -fsSL https://fileflows.com/downloads/zip -o "$temp_file"
|
||||||
$STD unzip -o -d /opt/fileflows "$temp_file"
|
$STD unzip -o -d /opt/fileflows "$temp_file"
|
||||||
rm -rf "$temp_file"
|
|
||||||
rm -rf "$backup_filename"
|
|
||||||
msg_ok "Updated $APP to latest version"
|
msg_ok "Updated $APP to latest version"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start fileflows
|
systemctl start fileflows
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf "$temp_file"
|
||||||
|
rm -rf "$backup_filename"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at latest version"
|
msg_ok "No update required. ${APP} is already at latest version"
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ function update_script() {
|
|||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start ghostfolio
|
systemctl start ghostfolio
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
$STD npm cache clean --force
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
__ __ __
|
|
||||||
/ / / /___ ____ _____ ____ / /_ ___ _____
|
|
||||||
/ / / / __ \/ __ `/ __ \/ __ \/ __ \/ _ \/ ___/
|
|
||||||
/ /_/ / /_/ / /_/ / /_/ / /_/ / / / / __/ /
|
|
||||||
\____/ .___/\__, /\____/ .___/_/ /_/\___/_/
|
|
||||||
/_/ /____/ /_/
|
|
||||||
@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
|
|||||||
var_ram="${var_ram:-1024}"
|
var_ram="${var_ram:-1024}"
|
||||||
var_disk="${var_disk:-4}"
|
var_disk="${var_disk:-4}"
|
||||||
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"
|
||||||
@@ -29,7 +29,7 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PYTHON_VERSION="3.12" setup_uv
|
setup_uv
|
||||||
|
|
||||||
if check_for_gh_release "huntarr" "plexguide/Huntarr.io"; then
|
if check_for_gh_release "huntarr" "plexguide/Huntarr.io"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
|
|||||||
29
ct/immich.sh
29
ct/immich.sh
@@ -61,15 +61,6 @@ EOF
|
|||||||
msg_ok "Installed libmimalloc3"
|
msg_ok "Installed libmimalloc3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f /etc/apt/sources.list.d/mise.list ]]; then
|
|
||||||
msg_info "Installing Mise"
|
|
||||||
curl -fSs https://mise.jdx.dev/gpg-key.pub | tee /etc/apt/keyrings/mise-archive-keyring.pub 1>/dev/null
|
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/mise-archive-keyring.pub arch=amd64] https://mise.jdx.dev/deb stable main" | tee /etc/apt/sources.list.d/mise.list
|
|
||||||
$STD apt update
|
|
||||||
$STD apt install -y mise
|
|
||||||
msg_ok "Installed Mise"
|
|
||||||
fi
|
|
||||||
|
|
||||||
STAGING_DIR=/opt/staging
|
STAGING_DIR=/opt/staging
|
||||||
BASE_DIR=${STAGING_DIR}/base-images
|
BASE_DIR=${STAGING_DIR}/base-images
|
||||||
SOURCE_DIR=${STAGING_DIR}/image-source
|
SOURCE_DIR=${STAGING_DIR}/image-source
|
||||||
@@ -102,7 +93,7 @@ EOF
|
|||||||
msg_ok "Image-processing libraries up to date"
|
msg_ok "Image-processing libraries up to date"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RELEASE="2.3.1"
|
RELEASE="2.2.3"
|
||||||
if check_for_gh_release "immich" "immich-app/immich" "${RELEASE}"; then
|
if check_for_gh_release "immich" "immich-app/immich" "${RELEASE}"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop immich-web
|
systemctl stop immich-web
|
||||||
@@ -130,7 +121,6 @@ EOF
|
|||||||
UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)"
|
UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)"
|
||||||
SRC_DIR="${INSTALL_DIR}/source"
|
SRC_DIR="${INSTALL_DIR}/source"
|
||||||
APP_DIR="${INSTALL_DIR}/app"
|
APP_DIR="${INSTALL_DIR}/app"
|
||||||
PLUGIN_DIR="${APP_DIR}/corePlugin"
|
|
||||||
ML_DIR="${APP_DIR}/machine-learning"
|
ML_DIR="${APP_DIR}/machine-learning"
|
||||||
GEO_DIR="${INSTALL_DIR}/geodata"
|
GEO_DIR="${INSTALL_DIR}/geodata"
|
||||||
|
|
||||||
@@ -155,7 +145,9 @@ EOF
|
|||||||
rm -rf "${APP_DIR:?}"/*
|
rm -rf "${APP_DIR:?}"/*
|
||||||
)
|
)
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v${RELEASE}" "$SRC_DIR"
|
rm -rf "$SRC_DIR"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v${RELEASE}" "$SRC_DIR"
|
||||||
|
|
||||||
msg_info "Updating ${APP} web and microservices"
|
msg_info "Updating ${APP} web and microservices"
|
||||||
cd "$SRC_DIR"/server
|
cd "$SRC_DIR"/server
|
||||||
@@ -188,18 +180,7 @@ EOF
|
|||||||
$STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli
|
$STD pnpm --filter @immich/cli --prod --no-optional deploy "$APP_DIR"/cli
|
||||||
cd "$APP_DIR"
|
cd "$APP_DIR"
|
||||||
mv "$INSTALL_DIR"/start.sh "$APP_DIR"/bin
|
mv "$INSTALL_DIR"/start.sh "$APP_DIR"/bin
|
||||||
|
msg_ok "Updated ${APP} web and microservices"
|
||||||
# plugins
|
|
||||||
cd "$SRC_DIR"
|
|
||||||
$STD mise trust --ignore ./mise.toml
|
|
||||||
$STD mise trust ./plugins/mise.toml
|
|
||||||
cd plugins
|
|
||||||
$STD mise install
|
|
||||||
$STD mise run build
|
|
||||||
mkdir -p "$PLUGIN_DIR"
|
|
||||||
cp -r ./dist "$PLUGIN_DIR"/dist
|
|
||||||
cp ./manifest.json "$PLUGIN_DIR"
|
|
||||||
msg_ok "Updated ${APP} server, web, cli and plugins"
|
|
||||||
|
|
||||||
cd "$SRC_DIR"/machine-learning
|
cd "$SRC_DIR"/machine-learning
|
||||||
mkdir -p "$ML_DIR" && chown -R immich:immich "$ML_DIR"
|
mkdir -p "$ML_DIR" && chown -R immich:immich "$ML_DIR"
|
||||||
|
|||||||
@@ -20,57 +20,62 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
|
|
||||||
if [[ ! -d /opt/jellyseerr ]]; then
|
if [[ ! -d /opt/jellyseerr ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(node -v | cut -c2-3)" -ne 22 ]; then
|
if [ "$(node -v | cut -c2-3)" -ne 22 ]; then
|
||||||
msg_info "Updating Node.js Repository"
|
msg_info "Updating Node.js Repository"
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
|
||||||
msg_ok "Updating Node.js Repository"
|
msg_ok "Updating Node.js Repository"
|
||||||
|
|
||||||
msg_info "Updating Packages"
|
msg_info "Updating Packages"
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get -y upgrade
|
$STD apt-get -y upgrade
|
||||||
msg_ok "Updating Packages"
|
msg_ok "Updating Packages"
|
||||||
fi
|
|
||||||
|
|
||||||
cd /opt/jellyseerr
|
msg_info "Cleaning up"
|
||||||
output=$(git pull --no-rebase)
|
apt-get -y autoremove
|
||||||
|
apt-get -y autoclean
|
||||||
|
msg_ok "Cleaning up"
|
||||||
|
fi
|
||||||
|
|
||||||
pnpm_current=$(pnpm --version 2>/dev/null)
|
cd /opt/jellyseerr
|
||||||
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/jellyseerr/package.json)
|
output=$(git pull --no-rebase)
|
||||||
|
|
||||||
if [ -z "$pnpm_current" ]; then
|
pnpm_current=$(pnpm --version 2>/dev/null)
|
||||||
msg_error "pnpm not found. Installing version $pnpm_desired..."
|
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/jellyseerr/package.json)
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
|
||||||
elif ! node -e "const semver = require('semver'); process.exit(semver.satisfies('$pnpm_current', '$pnpm_desired') ? 0 : 1)"; then
|
|
||||||
msg_error "Updating pnpm from version $pnpm_current to $pnpm_desired..."
|
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
|
||||||
else
|
|
||||||
msg_ok "pnpm is already installed and satisfies version $pnpm_desired."
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Updating $APP"
|
if [ -z "$pnpm_current" ]; then
|
||||||
if echo "$output" | grep -q "Already up to date."; then
|
msg_error "pnpm not found. Installing version $pnpm_desired..."
|
||||||
msg_ok "$APP is already up to date."
|
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
||||||
exit
|
elif ! node -e "const semver = require('semver'); process.exit(semver.satisfies('$pnpm_current', '$pnpm_desired') ? 0 : 1)"; then
|
||||||
fi
|
msg_error "Updating pnpm from version $pnpm_current to $pnpm_desired..."
|
||||||
|
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
||||||
|
else
|
||||||
|
msg_ok "pnpm is already installed and satisfies version $pnpm_desired."
|
||||||
|
fi
|
||||||
|
|
||||||
systemctl stop jellyseerr
|
msg_info "Updating $APP"
|
||||||
rm -rf dist .next node_modules
|
if echo "$output" | grep -q "Already up to date."; then
|
||||||
export CYPRESS_INSTALL_BINARY=0
|
msg_ok "$APP is already up to date."
|
||||||
cd /opt/jellyseerr
|
exit
|
||||||
$STD pnpm install --frozen-lockfile
|
fi
|
||||||
export NODE_OPTIONS="--max-old-space-size=3072"
|
|
||||||
$STD pnpm build
|
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
systemctl stop jellyseerr
|
||||||
|
rm -rf dist .next node_modules
|
||||||
|
export CYPRESS_INSTALL_BINARY=0
|
||||||
|
cd /opt/jellyseerr
|
||||||
|
$STD pnpm install --frozen-lockfile
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
|
$STD pnpm build
|
||||||
|
|
||||||
|
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=jellyseerr Service
|
Description=jellyseerr Service
|
||||||
After=network.target
|
After=network.target
|
||||||
@@ -86,10 +91,10 @@ ExecStart=/usr/bin/node dist/index.js
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl start jellyseerr
|
systemctl start jellyseerr
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated $APP"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
|
|||||||
APP="jotty"
|
APP="jotty"
|
||||||
var_tags="${var_tags:-tasks;notes}"
|
var_tags="${var_tags:-tasks;notes}"
|
||||||
var_cpu="${var_cpu:-2}"
|
var_cpu="${var_cpu:-2}"
|
||||||
var_ram="${var_ram:-3072}"
|
var_ram="${var_ram:-4096}"
|
||||||
var_disk="${var_disk:-6}"
|
var_disk="${var_disk:-6}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ function update_script() {
|
|||||||
cd /opt/karakeep/packages/db
|
cd /opt/karakeep/packages/db
|
||||||
$STD pnpm migrate
|
$STD pnpm migrate
|
||||||
$STD pnpm store prune
|
$STD pnpm store prune
|
||||||
sed -i "s/^SERVER_VERSION=.*$/SERVER_VERSION=${CHECK_UPDATE_RELEASE#v}/" /etc/karakeep/karakeep.env
|
sed -i "s/^SERVER_VERSION=.*$/SERVER_VERSION=${CHECK_UPDATE_RELEASE}/" /etc/karakeep/karakeep.env
|
||||||
msg_ok "Updated Karakeep"
|
msg_ok "Updated Karakeep"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
|
|||||||
47
ct/kasm.sh
47
ct/kasm.sh
@@ -25,51 +25,14 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -d /opt/kasm/current ]]; then
|
if [[ ! -d /var ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
msg_info "Updating LXC"
|
||||||
msg_info "Checking for new version"
|
$STD apt update
|
||||||
CURRENT_VERSION=$(readlink -f /opt/kasm/current | awk -F'/' '{print $4}')
|
$STD apt -y upgrade
|
||||||
KASM_URL=$(curl -fsSL "https://www.kasm.com/downloads" | tr '\n' ' ' | grep -oE 'https://kasm-static-content[^"]*kasm_release_[0-9]+\.[0-9]+\.[0-9]+\.[a-z0-9]+\.tar\.gz' | head -n 1)
|
msg_ok "Updated LXC"
|
||||||
if [[ -z "$KASM_URL" ]]; then
|
|
||||||
msg_error "Unable to detect latest Kasm release URL."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
KASM_VERSION=$(echo "$KASM_URL" | sed -E 's/.*kasm_release_([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
|
|
||||||
msg_info "Checked for new version"
|
|
||||||
|
|
||||||
msg_info "Removing outdated docker-compose plugin"
|
|
||||||
[ -f ~/.docker/cli-plugins/docker-compose ] && rm -rf ~/.docker/cli-plugins/docker-compose
|
|
||||||
msg_ok "Removed outdated docker-compose plugin"
|
|
||||||
|
|
||||||
if [[ -z "$CURRENT_VERSION" ]] || [[ "$KASM_VERSION" != "$CURRENT_VERSION" ]]; then
|
|
||||||
msg_info "Updating Kasm"
|
|
||||||
cd /tmp
|
|
||||||
|
|
||||||
msg_warn "WARNING: This script will run an external installer from a third-party source (https://www.kasmweb.com/)."
|
|
||||||
msg_warn "The following code is NOT maintained or audited by our repository."
|
|
||||||
msg_warn "If you have any doubts or concerns, please review the installer code before proceeding:"
|
|
||||||
msg_custom "${TAB3}${GATEWAY}${BGN}${CL}" "\e[1;34m" "→ upgrade.sh inside tar.gz $KASM_URL"
|
|
||||||
echo
|
|
||||||
read -r -p "${TAB3}Do you want to continue? [y/N]: " CONFIRM
|
|
||||||
if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
|
||||||
msg_error "Aborted by user. No changes have been made."
|
|
||||||
exit 10
|
|
||||||
fi
|
|
||||||
curl -fsSL -o "/tmp/kasm_release_${KASM_VERSION}.tar.gz" "$KASM_URL"
|
|
||||||
tar -xf "kasm_release_${KASM_VERSION}.tar.gz"
|
|
||||||
chmod +x /tmp/kasm_release/install.sh
|
|
||||||
rm -f /tmp/kasm_release_${KASM_VERSION}.tar.gz
|
|
||||||
|
|
||||||
bash /tmp/kasm_release/upgrade.sh --proxy-port 443
|
|
||||||
rm -rf /tmp/kasm_release
|
|
||||||
msg_ok "Updated Successfully"
|
|
||||||
else
|
|
||||||
msg_ok "No update required. Kasm is already at v${KASM_VERSION}"
|
|
||||||
|
|
||||||
fi
|
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,15 @@ function update_script() {
|
|||||||
cp -a keycloak.old/conf/. keycloak/conf/
|
cp -a keycloak.old/conf/. keycloak/conf/
|
||||||
cp -a keycloak.old/providers/. keycloak/providers/ 2>/dev/null || true
|
cp -a keycloak.old/providers/. keycloak/providers/ 2>/dev/null || true
|
||||||
cp -a keycloak.old/themes/. keycloak/themes/ 2>/dev/null || true
|
cp -a keycloak.old/themes/. keycloak/themes/ 2>/dev/null || true
|
||||||
rm -rf keycloak.old
|
|
||||||
msg_ok "Updated Keycloak"
|
msg_ok "Updated Keycloak"
|
||||||
|
|
||||||
msg_info "Restarting Service"
|
msg_info "Restarting Service"
|
||||||
systemctl restart keycloak
|
systemctl restart keycloak
|
||||||
msg_ok "Restarted Service"
|
msg_ok "Restarted Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf keycloak.old
|
||||||
|
msg_ok "Cleanup complete"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -50,12 +50,15 @@ function update_script() {
|
|||||||
$STD yarn install
|
$STD yarn install
|
||||||
$STD yarn build
|
$STD yarn build
|
||||||
chown -R www-data:www-data /opt/koillection/public/uploads
|
chown -R www-data:www-data /opt/koillection/public/uploads
|
||||||
rm -r /opt/koillection-backup
|
|
||||||
msg_ok "Updated Koillection"
|
msg_ok "Updated Koillection"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start apache2
|
systemctl start apache2
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -r /opt/koillection-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated Successfully!"
|
msg_ok "Updated Successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -52,14 +52,17 @@ function update_script() {
|
|||||||
$STD yarn web:build
|
$STD yarn web:build
|
||||||
$STD yarn prisma:deploy
|
$STD yarn prisma:deploy
|
||||||
[ -d /opt/data.bak ] && mv /opt/data.bak /opt/linkwarden/data
|
[ -d /opt/data.bak ] && mv /opt/data.bak /opt/linkwarden/data
|
||||||
rm -rf ~/.cargo/registry ~/.cargo/git ~/.cargo/.package-cache ~/.rustup
|
|
||||||
rm -rf /root/.cache/yarn
|
|
||||||
rm -rf /opt/linkwarden/.next/cache
|
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start linkwarden
|
systemctl start linkwarden
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf ~/.cargo/registry ~/.cargo/git ~/.cargo/.package-cache ~/.rustup
|
||||||
|
rm -rf /root/.cache/yarn
|
||||||
|
rm -rf /opt/linkwarden/.next/cache
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -42,12 +42,15 @@ function update_script() {
|
|||||||
mv /opt/listmonk-backup/config.toml /opt/listmonk/config.toml
|
mv /opt/listmonk-backup/config.toml /opt/listmonk/config.toml
|
||||||
mv /opt/listmonk-backup/uploads /opt/listmonk/uploads
|
mv /opt/listmonk-backup/uploads /opt/listmonk/uploads
|
||||||
$STD /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml
|
$STD /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml
|
||||||
rm -rf /opt/listmonk-backup/
|
|
||||||
msg_ok "Configured listmonk"
|
msg_ok "Configured listmonk"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start listmonk
|
systemctl start listmonk
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/listmonk-backup/
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -53,12 +53,15 @@ function update_script() {
|
|||||||
msg_info "Configuring LubeLogger"
|
msg_info "Configuring LubeLogger"
|
||||||
chmod 700 /opt/lubelogger/CarCareTracker
|
chmod 700 /opt/lubelogger/CarCareTracker
|
||||||
cp -rf /tmp/lubeloggerData/* /opt/lubelogger/
|
cp -rf /tmp/lubeloggerData/* /opt/lubelogger/
|
||||||
rm -rf /tmp/lubeloggerData
|
|
||||||
msg_ok "Configured LubeLogger"
|
msg_ok "Configured LubeLogger"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start lubelogger
|
systemctl start lubelogger
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /tmp/lubeloggerData
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -38,9 +38,15 @@ function update_script() {
|
|||||||
curl -fsSL -o "$DEB_FILE" "$DEB_URL"
|
curl -fsSL -o "$DEB_FILE" "$DEB_URL"
|
||||||
$STD apt install "$DEB_FILE" -y
|
$STD apt install "$DEB_FILE" -y
|
||||||
systemctl restart lyrion
|
systemctl restart lyrion
|
||||||
$STD rm -f "$DEB_FILE"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to ${RELEASE}"
|
msg_ok "Updated $APP to ${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD rm -f "$DEB_FILE"
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "$APP is already up to date (${RELEASE})"
|
msg_ok "$APP is already up to date (${RELEASE})"
|
||||||
|
|||||||
@@ -55,13 +55,17 @@ function update_script() {
|
|||||||
mv /usr/local/bin/minio /usr/local/bin/minio_bak
|
mv /usr/local/bin/minio /usr/local/bin/minio_bak
|
||||||
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/minio" -o /usr/local/bin/minio
|
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/minio" -o /usr/local/bin/minio
|
||||||
chmod +x /usr/local/bin/minio
|
chmod +x /usr/local/bin/minio
|
||||||
rm -f /usr/local/bin/minio_bak
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start minio
|
systemctl start minio
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -f /usr/local/bin/minio_bak
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -52,12 +52,15 @@ function update_script() {
|
|||||||
$STD php artisan monica:update --force
|
$STD php artisan monica:update --force
|
||||||
chown -R www-data:www-data /opt/monica
|
chown -R www-data:www-data /opt/monica
|
||||||
chmod -R 775 /opt/monica/storage
|
chmod -R 775 /opt/monica/storage
|
||||||
rm -r /opt/monica-backup
|
|
||||||
msg_ok "Configured monica"
|
msg_ok "Configured monica"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start apache2
|
systemctl start apache2
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -r /opt/monica-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -57,14 +57,17 @@ function update_script() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
$STD /opt/netbox/upgrade.sh
|
$STD /opt/netbox/upgrade.sh
|
||||||
rm -r "/opt/v${RELEASE}.zip"
|
|
||||||
rm -r /opt/netbox-backup
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start netbox netbox-rq
|
systemctl start netbox netbox-rq
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -r "/opt/v${RELEASE}.zip"
|
||||||
|
rm -r /opt/netbox-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function update_script() {
|
|||||||
msg_ok "Stopped services"
|
msg_ok "Stopped services"
|
||||||
|
|
||||||
msg_info "Backing up configurations"
|
msg_info "Backing up configurations"
|
||||||
cp /opt/netvisor/.env /opt/netvisor.env.bak
|
cp /opt/netvisor/.env /opt/netvisor.env
|
||||||
msg_ok "Backed up configurations"
|
msg_ok "Backed up configurations"
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "mayanayza/netvisor" "tarball" "latest" "/opt/netvisor"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "netvisor" "mayanayza/netvisor" "tarball" "latest" "/opt/netvisor"
|
||||||
@@ -49,16 +49,10 @@ function update_script() {
|
|||||||
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
TOOLCHAIN="$(grep "channel" /opt/netvisor/backend/rust-toolchain.toml | awk -F\" '{print $2}')"
|
||||||
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
RUST_TOOLCHAIN=$TOOLCHAIN setup_rust
|
||||||
|
|
||||||
cp /opt/netvisor.env.bak /opt/netvisor/.env
|
mv /opt/netvisor.env /opt/netvisor/.env
|
||||||
LOCAL_IP="$(hostname -I | awk '{print $1}')"
|
|
||||||
if ! grep -q "PUBLIC_URL" /opt/netvisor/.env; then
|
|
||||||
sed -i "\|_PATH=|a\NETVISOR_PUBLIC_URL=http://${LOCAL_IP}:60072" /opt/netvisor/.env
|
|
||||||
fi
|
|
||||||
sed -i 's|_TARGET=.*$|_URL=http://127.0.0.1:60072|' /opt/netvisor/.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=60072
|
||||||
cd /opt/netvisor/ui
|
cd /opt/netvisor/ui
|
||||||
$STD npm ci --no-fund --no-audit
|
$STD npm ci --no-fund --no-audit
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
@@ -70,16 +64,10 @@ function update_script() {
|
|||||||
mv ./target/release/server /usr/bin/netvisor-server
|
mv ./target/release/server /usr/bin/netvisor-server
|
||||||
msg_ok "Built Netvisor-server"
|
msg_ok "Built Netvisor-server"
|
||||||
|
|
||||||
msg_info "Building Netvisor-daemon"
|
msg_info "Building Netvisor-daemon (amd64 version)"
|
||||||
$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/netvisor-daemon
|
||||||
msg_ok "Built Netvisor-daemon"
|
msg_ok "Built Netvisor-daemon (amd64 version)"
|
||||||
|
|
||||||
sed -i -e 's|-target|-url|' \
|
|
||||||
-e 's| --server-port |:|' \
|
|
||||||
/etc/systemd/system/netvisor-daemon.service
|
|
||||||
sed -i '/^ \"server_target.*$/d' /root/.config/daemon/config.json
|
|
||||||
systemctl daemon-reload
|
|
||||||
|
|
||||||
msg_info "Starting services"
|
msg_info "Starting services"
|
||||||
systemctl start netvisor-server netvisor-daemon
|
systemctl start netvisor-server netvisor-daemon
|
||||||
|
|||||||
@@ -21,34 +21,37 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -d /opt/nextpvr ]]; then
|
if [[ ! -d /opt/nextpvr ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop nextpvr-server
|
||||||
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
|
msg_info "Updating LXC packages"
|
||||||
|
$STD apt update
|
||||||
|
$STD apt -y upgrade
|
||||||
|
msg_ok "Updated LXC packages"
|
||||||
|
|
||||||
|
msg_info "Updating ${APP}"
|
||||||
|
cd /opt
|
||||||
|
curl -fsSL "https://nextpvr.com/nextpvr-helper.deb" -o $(basename "https://nextpvr.com/nextpvr-helper.deb")
|
||||||
|
$STD dpkg -i nextpvr-helper.deb
|
||||||
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start nextpvr-server
|
||||||
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/nextpvr-helper.deb
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
fi
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop nextpvr-server
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
msg_info "Updating LXC packages"
|
|
||||||
$STD apt update
|
|
||||||
$STD apt -y upgrade
|
|
||||||
msg_ok "Updated LXC packages"
|
|
||||||
|
|
||||||
msg_info "Updating ${APP}"
|
|
||||||
cd /opt
|
|
||||||
curl -fsSL "https://nextpvr.com/nextpvr-helper.deb" -o $(basename "https://nextpvr.com/nextpvr-helper.deb")
|
|
||||||
$STD dpkg -i nextpvr-helper.deb
|
|
||||||
rm -rf /opt/nextpvr-helper.deb
|
|
||||||
msg_ok "Updated ${APP}"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start nextpvr-server
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
|||||||
@@ -49,13 +49,12 @@ function update_script() {
|
|||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||||
|
|
||||||
#RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
|
RELEASE=$(curl -fsSL https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest |
|
||||||
#grep "tag_name" |
|
grep "tag_name" |
|
||||||
#awk '{print substr($2, 3, length($2)-4) }')
|
awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager"
|
||||||
|
|
||||||
RELEASE="2.13.4"
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "nginxproxymanager" "NginxProxyManager/nginx-proxy-manager" "tarball" "v${RELEASE}" "/opt/nginxproxymanager"
|
|
||||||
|
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop openresty
|
systemctl stop openresty
|
||||||
systemctl stop npm
|
systemctl stop npm
|
||||||
|
|||||||
@@ -42,13 +42,17 @@ function update_script() {
|
|||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
export DEBCONF_NOWARNINGS=yes
|
export DEBCONF_NOWARNINGS=yes
|
||||||
$STD dpkg -i nxwitness-server-$RELEASE-linux_x64.deb
|
$STD dpkg -i nxwitness-server-$RELEASE-linux_x64.deb
|
||||||
rm -f /tmp/nxwitness-server-$RELEASE-linux_x64.deb
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start networkoptix-root-tool networkoptix-mediaserver
|
systemctl start networkoptix-root-tool networkoptix-mediaserver
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -f /tmp/nxwitness-server-$RELEASE-linux_x64.deb
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -50,13 +50,17 @@ function update_script() {
|
|||||||
msg_info "Updating ${APP} to ${LATEST_VERSION}"
|
msg_info "Updating ${APP} to ${LATEST_VERSION}"
|
||||||
curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb
|
curl -fsSL https://nightly.odoo.com/${RELEASE}/nightly/deb/odoo_${RELEASE}.latest_all.deb -o /opt/odoo.deb
|
||||||
$STD apt install -y /opt/odoo.deb
|
$STD apt install -y /opt/odoo.deb
|
||||||
rm -f /opt/odoo.deb
|
|
||||||
echo "$LATEST_VERSION" >/opt/${APP}_version.txt
|
echo "$LATEST_VERSION" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to ${LATEST_VERSION}"
|
msg_ok "Updated ${APP} to ${LATEST_VERSION}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting ${APP} service"
|
||||||
systemctl start odoo
|
systemctl start odoo
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f /opt/odoo.deb
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}"
|
msg_ok "No update required. ${APP} is already at ${LATEST_VERSION}"
|
||||||
|
|||||||
@@ -43,13 +43,16 @@ function update_script() {
|
|||||||
mkdir -p /usr/local/lib/ollama
|
mkdir -p /usr/local/lib/ollama
|
||||||
tar -xzf "${TMP_TAR}" -C /usr/local/lib/ollama
|
tar -xzf "${TMP_TAR}" -C /usr/local/lib/ollama
|
||||||
ln -sf /usr/local/lib/ollama/bin/ollama /usr/local/bin/ollama
|
ln -sf /usr/local/lib/ollama/bin/ollama /usr/local/bin/ollama
|
||||||
rm -f "${TMP_TAR}"
|
|
||||||
echo "${RELEASE}" >/opt/Ollama_version.txt
|
echo "${RELEASE}" >/opt/Ollama_version.txt
|
||||||
msg_ok "Updated Ollama to ${RELEASE}"
|
msg_ok "Updated Ollama to ${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
systemctl start ollama
|
systemctl start ollama
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f "${TMP_TAR}"
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. Ollama is already at ${RELEASE}"
|
msg_ok "No update required. Ollama is already at ${RELEASE}"
|
||||||
|
|||||||
16
ct/omada.sh
16
ct/omada.sh
@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
|
|||||||
var_ram="${var_ram:-3072}"
|
var_ram="${var_ram:-3072}"
|
||||||
var_disk="${var_disk:-8}"
|
var_disk="${var_disk:-8}"
|
||||||
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"
|
||||||
@@ -32,11 +32,19 @@ function update_script() {
|
|||||||
if lscpu | grep -q 'avx'; then
|
if lscpu | grep -q 'avx'; then
|
||||||
MONGO_VERSION="8.0" setup_mongodb
|
MONGO_VERSION="8.0" setup_mongodb
|
||||||
else
|
else
|
||||||
msg_error "No AVX detected (CPU-Flag)! We have discontinued support for this. You are welcome to try it manually with a Debian LXC, but due to the many issues with Omada, we currently only support AVX CPUs."
|
msg_warn "No AVX detected: Using older MongoDB 4.4"
|
||||||
exit 10
|
MONGO_VERSION="4.4" setup_mongodb
|
||||||
fi
|
fi
|
||||||
|
|
||||||
JAVA_VERSION="21" setup_java
|
msg_info "Checking if right Azul Zulu Java is installed"
|
||||||
|
java_version=$(java -version 2>&1 | awk -F[\"_] '/version/ {print $2}')
|
||||||
|
if [[ "$java_version" =~ ^1\.8\.* ]]; then
|
||||||
|
$STD apt remove --purge -y zulu8-jdk
|
||||||
|
$STD apt -y install zulu21-jre-headless
|
||||||
|
msg_ok "Updated Azul Zulu Java to 21"
|
||||||
|
else
|
||||||
|
msg_ok "Azul Zulu Java 21 already installed"
|
||||||
|
fi
|
||||||
|
|
||||||
msg_info "Updating Omada Controller"
|
msg_info "Updating Omada Controller"
|
||||||
OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" |
|
OMADA_URL=$(curl -fsSL "https://support.omadanetworks.com/en/download/software/omada-controller/" |
|
||||||
|
|||||||
@@ -39,14 +39,17 @@ function update_script() {
|
|||||||
tar -xzf onedev-latest.tar.gz
|
tar -xzf onedev-latest.tar.gz
|
||||||
$STD /opt/onedev-latest/bin/upgrade.sh /opt/onedev
|
$STD /opt/onedev-latest/bin/upgrade.sh /opt/onedev
|
||||||
RELEASE=$(cat /opt/onedev/release.properties | grep "version" | cut -d'=' -f2)
|
RELEASE=$(cat /opt/onedev/release.properties | grep "version" | cut -d'=' -f2)
|
||||||
rm -rf /opt/onedev-latest
|
|
||||||
rm -rf /opt/onedev-latest.tar.gz
|
|
||||||
echo "${RELEASE}" >"/opt/${APP}_version.txt"
|
echo "${RELEASE}" >"/opt/${APP}_version.txt"
|
||||||
msg_ok "Updated ${APP} to v${RELEASE}"
|
msg_ok "Updated ${APP} to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start onedev
|
systemctl start onedev
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/onedev-latest
|
||||||
|
rm -rf /opt/onedev-latest.tar.gz
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}."
|
msg_ok "No update required. ${APP} is already at v${RELEASE}."
|
||||||
|
|||||||
@@ -65,14 +65,17 @@ EOF
|
|||||||
$STD pip install --no-cache-dir -r requirements.txt
|
$STD pip install --no-cache-dir -r requirements.txt
|
||||||
mkdir -p data/chromadb
|
mkdir -p data/chromadb
|
||||||
$STD npm install
|
$STD npm install
|
||||||
rm -rf /opt/v${RELEASE}.zip
|
|
||||||
rm -rf /opt/paperless-ai_bak
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start paperless-ai
|
systemctl start paperless-ai
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/v${RELEASE}.zip
|
||||||
|
rm -rf /opt/paperless-ai_bak
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -20,45 +20,48 @@ color
|
|||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -d /opt/paperless-gpt ]]; then
|
if [[ ! -d /opt/paperless-gpt ]]; then
|
||||||
msg_error "No Paperless-GPT installation found!"
|
msg_error "No Paperless-GPT installation found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
RELEASE=$(curl -fsSL https://api.github.com/repos/icereed/paperless-gpt/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
||||||
|
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||||
|
msg_info "Stopping Service"
|
||||||
|
systemctl stop paperless-gpt
|
||||||
|
msg_ok "Service Stopped"
|
||||||
|
|
||||||
|
msg_info "Updating Paperless-GPT to ${RELEASE}"
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
|
||||||
|
tar zxf $temp_file
|
||||||
|
rm -rf /opt/paperless-gpt
|
||||||
|
mv paperless-gpt-${RELEASE} /opt/paperless-gpt
|
||||||
|
cd /opt/paperless-gpt/web-app
|
||||||
|
$STD npm install
|
||||||
|
$STD npm run build
|
||||||
|
cd /opt/paperless-gpt
|
||||||
|
go mod download
|
||||||
|
export CC=musl-gcc
|
||||||
|
CGO_ENABLED=1 go build -tags musl -o /dev/null github.com/mattn/go-sqlite3
|
||||||
|
CGO_ENABLED=1 go build -tags musl -o paperless-gpt .
|
||||||
|
echo "${RELEASE}" >"/opt/paperless-gpt_version.txt"
|
||||||
|
msg_ok "Updated Paperless-GPT to ${RELEASE}"
|
||||||
|
|
||||||
|
msg_info "Starting Service"
|
||||||
|
systemctl start paperless-gpt
|
||||||
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f $temp_file
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
|
msg_ok "Updated successfully!"
|
||||||
|
else
|
||||||
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
fi
|
||||||
exit
|
exit
|
||||||
fi
|
|
||||||
RELEASE=$(curl -fsSL https://api.github.com/repos/icereed/paperless-gpt/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
|
|
||||||
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop paperless-gpt
|
|
||||||
msg_ok "Service Stopped"
|
|
||||||
|
|
||||||
msg_info "Updating Paperless-GPT to ${RELEASE}"
|
|
||||||
temp_file=$(mktemp)
|
|
||||||
curl -fsSL "https://github.com/icereed/paperless-gpt/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
|
|
||||||
tar zxf $temp_file
|
|
||||||
rm -rf /opt/paperless-gpt
|
|
||||||
mv paperless-gpt-${RELEASE} /opt/paperless-gpt
|
|
||||||
cd /opt/paperless-gpt/web-app
|
|
||||||
$STD npm install
|
|
||||||
$STD npm run build
|
|
||||||
cd /opt/paperless-gpt
|
|
||||||
go mod download
|
|
||||||
export CC=musl-gcc
|
|
||||||
CGO_ENABLED=1 go build -tags musl -o /dev/null github.com/mattn/go-sqlite3
|
|
||||||
CGO_ENABLED=1 go build -tags musl -o paperless-gpt .
|
|
||||||
rm -f $temp_file
|
|
||||||
echo "${RELEASE}" >"/opt/paperless-gpt_version.txt"
|
|
||||||
msg_ok "Updated Paperless-GPT to ${RELEASE}"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start paperless-gpt
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
else
|
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
|||||||
@@ -52,14 +52,17 @@ function update_script() {
|
|||||||
$STD php bin/console cache:clear
|
$STD php bin/console cache:clear
|
||||||
$STD php bin/console doctrine:migrations:migrate -n
|
$STD php bin/console doctrine:migrations:migrate -n
|
||||||
chown -R www-data:www-data /opt/partdb
|
chown -R www-data:www-data /opt/partdb
|
||||||
rm -r "/opt/v${RELEASE}.zip"
|
|
||||||
rm -r /opt/partdb-backup
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start apache2
|
systemctl start apache2
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -r "/opt/v${RELEASE}.zip"
|
||||||
|
rm -r /opt/partdb-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ function update_script() {
|
|||||||
$STD php artisan migrate --seed --force
|
$STD php artisan migrate --seed --force
|
||||||
chown -R www-data:www-data /opt/pelican-panel
|
chown -R www-data:www-data /opt/pelican-panel
|
||||||
chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/
|
chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/
|
||||||
rm -rf "/opt/pelican-panel/panel.tar.gz"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
@@ -75,6 +74,10 @@ function update_script() {
|
|||||||
$STD php artisan queue:restart
|
$STD php artisan queue:restart
|
||||||
$STD php artisan up
|
$STD php artisan up
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf "/opt/pelican-panel/panel.tar.gz"
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ function update_script() {
|
|||||||
header_info
|
header_info
|
||||||
check_container_storage
|
check_container_storage
|
||||||
check_container_resources
|
check_container_resources
|
||||||
if [[ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] \
|
if [ ! -f /etc/apt/sources.list.d/plexmediaserver.list ]] && [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
|
||||||
&& [[ ! -f /etc/apt/sources.list.d/plexmediaserver.sources ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ EOF
|
|||||||
$STD php artisan migrate --seed --force --no-interaction
|
$STD php artisan migrate --seed --force --no-interaction
|
||||||
chown -R www-data:www-data /opt/pterodactyl-panel/*
|
chown -R www-data:www-data /opt/pterodactyl-panel/*
|
||||||
chmod -R 755 /opt/pterodactyl-panel/storage /opt/pterodactyl-panel/bootstrap/cache/
|
chmod -R 755 /opt/pterodactyl-panel/storage /opt/pterodactyl-panel/bootstrap/cache/
|
||||||
rm -rf "/opt/pterodactyl-panel/panel.tar.gz"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
@@ -78,6 +77,10 @@ EOF
|
|||||||
$STD php artisan queue:restart
|
$STD php artisan queue:restart
|
||||||
$STD php artisan up
|
$STD php artisan up
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf "/opt/pterodactyl-panel/panel.tar.gz"
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -43,11 +43,14 @@ function update_script() {
|
|||||||
$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 dotnet-sdk-9.0
|
||||||
fi
|
fi
|
||||||
rm -rf /opt/rdtc-backup
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start rdtc
|
systemctl start rdtc
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/rdtc-backup
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ function update_script() {
|
|||||||
cd /tmp
|
cd /tmp
|
||||||
curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb
|
curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb
|
||||||
$STD dpkg -i minio.deb
|
$STD dpkg -i minio.deb
|
||||||
rm -f /tmp/minio.deb
|
|
||||||
msg_ok "Updated Minio"
|
msg_ok "Updated Minio"
|
||||||
|
|
||||||
msg_info "Updating Browserless (Patience)"
|
msg_info "Updating Browserless (Patience)"
|
||||||
@@ -76,12 +75,16 @@ function update_script() {
|
|||||||
$STD npm run build:function
|
$STD npm run build:function
|
||||||
$STD npm prune production
|
$STD npm prune production
|
||||||
mv /opt/browserless.env /opt/browserless/.env
|
mv /opt/browserless.env /opt/browserless/.env
|
||||||
rm -f "$brwsr_tmp"
|
|
||||||
msg_ok "Updated Browserless"
|
msg_ok "Updated Browserless"
|
||||||
|
|
||||||
msg_info "Restarting services"
|
msg_info "Restarting services"
|
||||||
systemctl start minio Reactive-Resume browserless
|
systemctl start minio Reactive-Resume browserless
|
||||||
msg_ok "Restarted services"
|
msg_ok "Restarted services"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f /tmp/minio.deb
|
||||||
|
rm -f "$brwsr_tmp"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -41,12 +41,15 @@ function update_script() {
|
|||||||
$STD npm install
|
$STD npm install
|
||||||
cp -f /opt/index.html /opt/revealjs
|
cp -f /opt/index.html /opt/revealjs
|
||||||
sed -i '25s/localhost/0.0.0.0/g' /opt/revealjs/gulpfile.js
|
sed -i '25s/localhost/0.0.0.0/g' /opt/revealjs/gulpfile.js
|
||||||
rm -f /opt/index.html
|
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated $APP"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start revealjs
|
systemctl start revealjs
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f /opt/index.html
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -61,12 +61,15 @@ function update_script() {
|
|||||||
$STD pip install -r requirements.txt
|
$STD pip install -r requirements.txt
|
||||||
mv /opt/config.ini.bak /opt/soularr/config.ini
|
mv /opt/config.ini.bak /opt/soularr/config.ini
|
||||||
mv /opt/run.sh.bak /opt/soularr/run.sh
|
mv /opt/run.sh.bak /opt/soularr/run.sh
|
||||||
rm -rf /tmp/main.zip
|
|
||||||
msg_ok "Updated soularr"
|
msg_ok "Updated soularr"
|
||||||
|
|
||||||
msg_info "Starting soularr timer"
|
msg_info "Starting soularr timer"
|
||||||
systemctl start soularr.timer
|
systemctl start soularr.timer
|
||||||
msg_ok "Started soularr timer"
|
msg_ok "Started soularr timer"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /tmp/main.zip
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function update_script() {
|
|||||||
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
|
||||||
|
|
||||||
if check_for_gh_release "snipe-it" "grokability/snipe-it"; then
|
if check_for_gh_release "snipe-it" "snipe/snipe-it"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop nginx
|
systemctl stop nginx
|
||||||
msg_ok "Services Stopped"
|
msg_ok "Services Stopped"
|
||||||
@@ -40,7 +40,7 @@ function update_script() {
|
|||||||
mv /opt/snipe-it /opt/snipe-it-backup
|
mv /opt/snipe-it /opt/snipe-it-backup
|
||||||
msg_ok "Backup created"
|
msg_ok "Backup created"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "snipe-it" "grokability/snipe-it" "tarball"
|
fetch_and_deploy_gh_release "snipe-it" "snipe/snipe-it" "tarball"
|
||||||
[[ "$(php -v 2>/dev/null)" == PHP\ 8.2* ]] && PHP_VERSION="8.3" PHP_MODULE="common,ctype,ldap,fileinfo,iconv,mysql,soap,xsl" PHP_FPM="YES" setup_php
|
[[ "$(php -v 2>/dev/null)" == PHP\ 8.2* ]] && PHP_VERSION="8.3" PHP_MODULE="common,ctype,ldap,fileinfo,iconv,mysql,soap,xsl" PHP_FPM="YES" setup_php
|
||||||
sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/snipeit.conf
|
sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/snipeit.conf
|
||||||
setup_composer
|
setup_composer
|
||||||
|
|||||||
@@ -43,13 +43,17 @@ function update_script() {
|
|||||||
cd spoolman
|
cd spoolman
|
||||||
$STD pip3 install -r requirements.txt
|
$STD pip3 install -r requirements.txt
|
||||||
curl -fsSL "https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example" -o ".env"
|
curl -fsSL "https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example" -o ".env"
|
||||||
rm -rf /opt/spoolman.zip
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP} to ${RELEASE}"
|
msg_ok "Updated ${APP} to ${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start spoolman
|
systemctl start spoolman
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/spoolman.zip
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -64,13 +64,16 @@ EOF
|
|||||||
cd /opt/tandoor
|
cd /opt/tandoor
|
||||||
$STD /opt/tandoor/.venv/bin/python manage.py migrate
|
$STD /opt/tandoor/.venv/bin/python manage.py migrate
|
||||||
$STD /opt/tandoor/.venv/bin/python manage.py collectstatic --no-input
|
$STD /opt/tandoor/.venv/bin/python manage.py collectstatic --no-input
|
||||||
rm -rf /opt/tandoor.bak
|
|
||||||
msg_ok "Updated Trandoor"
|
msg_ok "Updated Trandoor"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start tandoor
|
systemctl start tandoor
|
||||||
systemctl reload nginx
|
systemctl reload nginx
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/tandoor.bak
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -45,13 +45,16 @@ function update_script() {
|
|||||||
export NODE_OPTIONS=--openssl-legacy-provider
|
export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
$STD npm i
|
$STD npm i
|
||||||
$STD yarn build
|
$STD yarn build
|
||||||
rm -r "/opt/v${RELEASE}.tar.gz"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
|
||||||
msg_ok "Updated TasmoCompiler"
|
msg_ok "Updated TasmoCompiler"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start tasmocompiler
|
systemctl start tasmocompiler
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -r "/opt/v${RELEASE}.tar.gz"
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -37,8 +37,11 @@ function update_script() {
|
|||||||
$STD unzip Tdarr_Updater.zip
|
$STD unzip Tdarr_Updater.zip
|
||||||
chmod +x Tdarr_Updater
|
chmod +x Tdarr_Updater
|
||||||
$STD ./Tdarr_Updater
|
$STD ./Tdarr_Updater
|
||||||
rm -rf /opt/tdarr/Tdarr_Updater.zip
|
|
||||||
msg_ok "Updated Tdarr"
|
msg_ok "Updated Tdarr"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/tdarr/Tdarr_Updater.zip
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,11 @@ function update_script() {
|
|||||||
msg_info "Updating Technitium DNS"
|
msg_info "Updating Technitium DNS"
|
||||||
curl -fsSL "https://download.technitium.com/dns/DnsServerPortable.tar.gz" -o /opt/DnsServerPortable.tar.gz
|
curl -fsSL "https://download.technitium.com/dns/DnsServerPortable.tar.gz" -o /opt/DnsServerPortable.tar.gz
|
||||||
$STD tar zxvf /opt/DnsServerPortable.tar.gz -C /opt/technitium/dns/
|
$STD tar zxvf /opt/DnsServerPortable.tar.gz -C /opt/technitium/dns/
|
||||||
rm -f /opt/DnsServerPortable.tar.gz
|
|
||||||
msg_ok "Updated Technitium DNS"
|
msg_ok "Updated Technitium DNS"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -f /opt/DnsServerPortable.tar.gz
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. Technitium DNS is already at v${RELEASE}."
|
msg_ok "No update required. Technitium DNS is already at v${RELEASE}."
|
||||||
|
|||||||
@@ -41,12 +41,15 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Restoring data"
|
msg_info "Restoring data"
|
||||||
cp -R /opt/teddycloud_bak/certs /opt/teddycloud_bak/config /opt/teddycloud_bak/data /opt/teddycloud
|
cp -R /opt/teddycloud_bak/certs /opt/teddycloud_bak/config /opt/teddycloud_bak/data /opt/teddycloud
|
||||||
rm -rf /opt/teddycloud_bak
|
|
||||||
msg_ok "Data restored"
|
msg_ok "Data restored"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start teddycloud
|
systemctl start teddycloud
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/teddycloud_bak
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
15
ct/tianji.sh
15
ct/tianji.sh
@@ -43,7 +43,7 @@ function update_script() {
|
|||||||
|
|
||||||
fetch_and_deploy_gh_release "tianji" "msgbyte/tianji"
|
fetch_and_deploy_gh_release "tianji" "msgbyte/tianji"
|
||||||
|
|
||||||
msg_info "Updating Tianji"
|
msg_info "Updating ${APP}"
|
||||||
cd /opt/tianji
|
cd /opt/tianji
|
||||||
export NODE_OPTIONS="--max_old_space_size=4096"
|
export NODE_OPTIONS="--max_old_space_size=4096"
|
||||||
$STD pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile
|
$STD pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile
|
||||||
@@ -55,11 +55,7 @@ function update_script() {
|
|||||||
mv /opt/.env /opt/tianji/src/server/.env
|
mv /opt/.env /opt/tianji/src/server/.env
|
||||||
cd src/server
|
cd src/server
|
||||||
$STD pnpm db:migrate:apply
|
$STD pnpm db:migrate:apply
|
||||||
rm -rf /opt/tianji_bak
|
msg_ok "Updated ${APP}"
|
||||||
rm -rf /opt/tianji/src/client
|
|
||||||
rm -rf /opt/tianji/website
|
|
||||||
rm -rf /opt/tianji/reporter
|
|
||||||
msg_ok "Updated Tianji"
|
|
||||||
|
|
||||||
msg_info "Updating AppRise"
|
msg_info "Updating AppRise"
|
||||||
$STD uv pip install apprise cryptography --system
|
$STD uv pip install apprise cryptography --system
|
||||||
@@ -68,6 +64,13 @@ function update_script() {
|
|||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start tianji
|
systemctl start tianji
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/tianji_bak
|
||||||
|
rm -rf /opt/tianji/src/client
|
||||||
|
rm -rf /opt/tianji/website
|
||||||
|
rm -rf /opt/tianji/reporter
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -50,12 +50,18 @@ function update_script() {
|
|||||||
mv /opt/traccar.xml /opt/traccar/conf
|
mv /opt/traccar.xml /opt/traccar/conf
|
||||||
[[ -d /opt/data ]] && mv /opt/data /opt/traccar
|
[[ -d /opt/data ]] && mv /opt/data /opt/traccar
|
||||||
[[ -d /opt/media ]] && mv /opt/media /opt/traccar
|
[[ -d /opt/media ]] && mv /opt/media /opt/traccar
|
||||||
[ -f README.txt ] || [ -f traccar.run ] && rm -f README.txt traccar.run
|
|
||||||
msg_ok "Data restored"
|
msg_ok "Data restored"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start traccar
|
systemctl start traccar
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
[ -f README.txt ] || [ -f traccar.run ] && rm -f README.txt traccar.run
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -55,9 +55,15 @@ function update_script() {
|
|||||||
msg_info "Restoring Database"
|
msg_info "Restoring Database"
|
||||||
mkdir -p "$(dirname "${DB_RESTORE_PATH}")"
|
mkdir -p "$(dirname "${DB_RESTORE_PATH}")"
|
||||||
cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}"
|
cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}"
|
||||||
rm -rf /opt/trilium_backup
|
|
||||||
msg_ok "Restored Database"
|
msg_ok "Restored Database"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/trilium_backup
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start trilium
|
systemctl start trilium
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ function update_script() {
|
|||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start uhf-server
|
systemctl start uhf-server
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/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: Eduard González (wanetty)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/wanetty/upgopher
|
|
||||||
|
|
||||||
APP="Upgopher"
|
|
||||||
var_tags="${var_tags:-file-sharing}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-512}"
|
|
||||||
var_disk="${var_disk:-4}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
if [[ ! -d /opt/upgopher ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "upgopher" "wanetty/upgopher"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop upgopher
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "upgopher" "wanetty/upgopher" "prebuild" "latest" "/opt/upgopher" "upgopher_*_linux_amd64.tar.gz"
|
|
||||||
chmod +x /opt/upgopher/upgopher
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start upgopher
|
|
||||||
msg_ok "Started Service"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9090${CL}"
|
|
||||||
@@ -57,9 +57,12 @@ function update_script() {
|
|||||||
else
|
else
|
||||||
cp target/release/vaultwarden /opt/vaultwarden/bin/
|
cp target/release/vaultwarden /opt/vaultwarden/bin/
|
||||||
fi
|
fi
|
||||||
cd ~ && rm -rf vaultwarden
|
|
||||||
msg_ok "Updated VaultWarden"
|
msg_ok "Updated VaultWarden"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
cd ~ && rm -rf vaultwarden
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start vaultwarden
|
systemctl start vaultwarden
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
@@ -74,9 +77,12 @@ function update_script() {
|
|||||||
msg_info "Updating Web-Vault to $WVRELEASE"
|
msg_info "Updating Web-Vault to $WVRELEASE"
|
||||||
$STD curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/"$WVRELEASE"/bw_web_"$WVRELEASE".tar.gz
|
$STD curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/"$WVRELEASE"/bw_web_"$WVRELEASE".tar.gz
|
||||||
$STD tar -zxf bw_web_"$WVRELEASE".tar.gz -C /opt/vaultwarden/
|
$STD tar -zxf bw_web_"$WVRELEASE".tar.gz -C /opt/vaultwarden/
|
||||||
rm bw_web_"$WVRELEASE".tar.gz
|
|
||||||
msg_ok "Updated Web-Vault"
|
msg_ok "Updated Web-Vault"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm bw_web_"$WVRELEASE".tar.gz
|
||||||
|
msg_ok "Cleaned"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start vaultwarden
|
systemctl start vaultwarden
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|||||||
@@ -39,13 +39,16 @@ function update_script() {
|
|||||||
curl -fsSL "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb" -o $(basename "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb")
|
curl -fsSL "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb" -o $(basename "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb")
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
$STD dpkg -i vikunja-"$RELEASE"-amd64.deb
|
$STD dpkg -i vikunja-"$RELEASE"-amd64.deb
|
||||||
rm -rf /opt/vikunja-"$RELEASE"-amd64.deb
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated ${APP}"
|
msg_ok "Updated ${APP}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start vikunja
|
systemctl start vikunja
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/vikunja-"$RELEASE"-amd64.deb
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
msg_ok "No update required. ${APP} is already at ${RELEASE}"
|
||||||
|
|||||||
@@ -73,13 +73,16 @@ EOF
|
|||||||
cp -f wastebin* /opt/wastebin/
|
cp -f wastebin* /opt/wastebin/
|
||||||
chmod +x /opt/wastebin/wastebin
|
chmod +x /opt/wastebin/wastebin
|
||||||
chmod +x /opt/wastebin/wastebin-ctl
|
chmod +x /opt/wastebin/wastebin-ctl
|
||||||
rm -f "$temp_file"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated Wastebin"
|
msg_ok "Updated Wastebin"
|
||||||
|
|
||||||
msg_info "Starting Wastebin"
|
msg_info "Starting Wastebin"
|
||||||
systemctl start wastebin
|
systemctl start wastebin
|
||||||
msg_ok "Started Wastebin"
|
msg_ok "Started Wastebin"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -f "$temp_file"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ function update_script() {
|
|||||||
fetch_and_deploy_gh_release "watchyourlan" "aceberg/WatchYourLAN" "binary"
|
fetch_and_deploy_gh_release "watchyourlan" "aceberg/WatchYourLAN" "binary"
|
||||||
cp -R config.yaml /data/config.yaml
|
cp -R config.yaml /data/config.yaml
|
||||||
sed -i 's|/etc/watchyourlan/config.yaml|/data/config.yaml|' /lib/systemd/system/watchyourlan.service
|
sed -i 's|/etc/watchyourlan/config.yaml|/data/config.yaml|' /lib/systemd/system/watchyourlan.service
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
rm ~/config.yaml
|
rm ~/config.yaml
|
||||||
|
msg_ok "Cleaned up"
|
||||||
|
|
||||||
msg_info "Starting service"
|
msg_info "Starting service"
|
||||||
systemctl enable -q --now watchyourlan
|
systemctl enable -q --now watchyourlan
|
||||||
|
|||||||
@@ -45,13 +45,16 @@ function update_script() {
|
|||||||
$STD python3 manage.py collectstatic --no-input
|
$STD python3 manage.py collectstatic --no-input
|
||||||
$STD yarn install
|
$STD yarn install
|
||||||
$STD yarn build:css:sass
|
$STD yarn build:css:sass
|
||||||
rm -rf "$temp_file"
|
|
||||||
echo "${RELEASE}" >/opt/${APP}_version.txt
|
echo "${RELEASE}" >/opt/${APP}_version.txt
|
||||||
msg_ok "Updated $APP to v${RELEASE}"
|
msg_ok "Updated $APP to v${RELEASE}"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start wger
|
systemctl start wger
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf "$temp_file"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
else
|
else
|
||||||
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
msg_ok "No update required. ${APP} is already at v${RELEASE}"
|
||||||
|
|||||||
@@ -54,12 +54,15 @@ function update_script() {
|
|||||||
msg_info "Restoring Data"
|
msg_info "Restoring Data"
|
||||||
cp -R /opt/wikijs-backup/* /opt/wikijs
|
cp -R /opt/wikijs-backup/* /opt/wikijs
|
||||||
$SQLITE_INSTALL && $STD npm rebuild sqlite3
|
$SQLITE_INSTALL && $STD npm rebuild sqlite3
|
||||||
rm -rf /opt/wikijs-backup
|
|
||||||
msg_ok "Restored Data"
|
msg_ok "Restored Data"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start wikijs
|
systemctl start wikijs
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /opt/wikijs-backup
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -56,12 +56,15 @@ function update_script() {
|
|||||||
if ! grep -q 'frozen' /opt/wizarr/start.sh; then
|
if ! grep -q 'frozen' /opt/wizarr/start.sh; then
|
||||||
sed -i 's/run/& --frozen/' /opt/wizarr/start.sh
|
sed -i 's/run/& --frozen/' /opt/wizarr/start.sh
|
||||||
fi
|
fi
|
||||||
rm -rf "$BACKUP_FILE"
|
|
||||||
msg_ok "Updated Wizarr"
|
msg_ok "Updated Wizarr"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start wizarr
|
systemctl start wizarr
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf "$BACKUP_FILE"
|
||||||
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ function update_script() {
|
|||||||
xargs -I{} echo "https://repo.zabbix.com/zabbix/{}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb")" \
|
xargs -I{} echo "https://repo.zabbix.com/zabbix/{}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb")" \
|
||||||
-o /tmp/zabbix-release_latest+debian13_all.deb
|
-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
|
|
||||||
$STD apt update
|
$STD apt update
|
||||||
|
|
||||||
$STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql
|
$STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql
|
||||||
@@ -89,6 +88,13 @@ function update_script() {
|
|||||||
systemctl start "$AGENT_SERVICE"
|
systemctl start "$AGENT_SERVICE"
|
||||||
systemctl restart apache2
|
systemctl restart apache2
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
|
|
||||||
|
msg_info "Cleaning Up"
|
||||||
|
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
|
||||||
|
$STD apt -y autoremove
|
||||||
|
$STD apt -y autoclean
|
||||||
|
$STD apt -y clean
|
||||||
|
msg_ok "Cleaned"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,18 @@ function update_script() {
|
|||||||
rm -rf /opt/zigbee2mqtt/data
|
rm -rf /opt/zigbee2mqtt/data
|
||||||
mv /opt/z2m_backup/data /opt/zigbee2mqtt
|
mv /opt/z2m_backup/data /opt/zigbee2mqtt
|
||||||
cd /opt/zigbee2mqtt
|
cd /opt/zigbee2mqtt
|
||||||
grep -q "^packageImportMethod" ./pnpm-workspace.yaml || echo "packageImportMethod: hardlink" >>./pnpm-workspace.yaml
|
grep -q "^packageImportMethod" ./pnpm-workspace.yaml || echo "packageImportMethod: hardlink" >> ./pnpm-workspace.yaml
|
||||||
$STD pnpm install --frozen-lockfile
|
$STD pnpm install --frozen-lockfile
|
||||||
$STD pnpm build
|
$STD pnpm build
|
||||||
rm -rf /opt/z2m_backup
|
|
||||||
msg_ok "Updated Zigbee2MQTT"
|
msg_ok "Updated Zigbee2MQTT"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start zigbee2mqtt
|
systemctl start zigbee2mqtt
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
rm -rf /opt/z2m_backup
|
||||||
|
msg_ok "Cleaned up"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
|
|||||||
934
frontend/bun.lock
generated
934
frontend/bun.lock
generated
File diff suppressed because it is too large
Load Diff
10
frontend/package.json
generated
10
frontend/package.json
generated
@@ -23,7 +23,6 @@
|
|||||||
"@radix-ui/react-label": "^2.1.2",
|
"@radix-ui/react-label": "^2.1.2",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.5",
|
"@radix-ui/react-navigation-menu": "^1.2.5",
|
||||||
"@radix-ui/react-popover": "^1.1.6",
|
"@radix-ui/react-popover": "^1.1.6",
|
||||||
"@radix-ui/react-scroll-area": "^1.2.10",
|
|
||||||
"@radix-ui/react-select": "^2.1.6",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.2",
|
"@radix-ui/react-separator": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "^1.1.2",
|
"@radix-ui/react-slot": "^1.1.2",
|
||||||
@@ -37,24 +36,27 @@
|
|||||||
"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": "^11.18.2",
|
"framer-motion": "^11.18.2",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"lucide-react": "^0.554.0",
|
"lucide-react": "^0.542.0",
|
||||||
"mini-svg-data-uri": "^1.4.4",
|
"mini-svg-data-uri": "^1.4.4",
|
||||||
"motion": "^12.23.12",
|
"motion": "^12.23.12",
|
||||||
"next": "15.5.2",
|
"next": "15.5.2",
|
||||||
"next-themes": "^0.4.4",
|
"next-themes": "^0.4.4",
|
||||||
"nuqs": "^2.4.1",
|
"nuqs": "^2.4.1",
|
||||||
|
"pocketbase": "^0.21.5",
|
||||||
"prettier-plugin-organize-imports": "^4.1.0",
|
"prettier-plugin-organize-imports": "^4.1.0",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-chartjs-2": "^5.3.0",
|
"react-chartjs-2": "^5.3.0",
|
||||||
|
"react-code-blocks": "^0.1.6",
|
||||||
|
"react-datepicker": "^7.6.0",
|
||||||
"react-day-picker": "^9.4.3",
|
"react-day-picker": "^9.4.3",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
|
"react-simple-typewriter": "^5.0.1",
|
||||||
"react-use-measure": "^2.1.7",
|
"react-use-measure": "^2.1.7",
|
||||||
"recharts": "2.15.4",
|
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
|
"simple-icons": "^13.21.0",
|
||||||
"sonner": "^1.7.4",
|
"sonner": "^1.7.4",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 8080,
|
"interface_port": 8080,
|
||||||
"documentation": null,
|
"documentation": null,
|
||||||
"website": "https://filebrowser.org/index.html#features",
|
"website": "https://filebrowser.org/features",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/file-browser.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/file-browser.webp",
|
||||||
"config_path": "",
|
"config_path": "",
|
||||||
"description": "File Browser offers a user-friendly web interface for managing files within a designated directory. It allows you to perform various actions such as uploading, deleting, previewing, renaming, and editing files.",
|
"description": "File Browser offers a user-friendly web interface for managing files within a designated directory. It allows you to perform various actions such as uploading, deleting, previewing, renaming, and editing files.",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
"ram": 1024,
|
"ram": 1024,
|
||||||
"hdd": 4,
|
"hdd": 4,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"script": "ct/jotty.sh",
|
"script": "ct/jotty.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 2,
|
"cpu": 2,
|
||||||
"ram": 3072,
|
"ram": 4096,
|
||||||
"hdd": 6,
|
"hdd": 6,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "13"
|
"version": "13"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
],
|
],
|
||||||
"date_created": "2025-05-26",
|
"date_created": "2025-05-26",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": false,
|
||||||
"privileged": true,
|
"privileged": true,
|
||||||
"config_path": "",
|
"config_path": "",
|
||||||
"interface_port": 443,
|
"interface_port": 443,
|
||||||
|
|||||||
@@ -23,18 +23,13 @@
|
|||||||
"ram": 2048,
|
"ram": 2048,
|
||||||
"hdd": 4,
|
"hdd": 4,
|
||||||
"os": "Debian",
|
"os": "Debian",
|
||||||
"version": "13"
|
"version": "12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default_credentials": {
|
"default_credentials": {
|
||||||
"username": null,
|
"username": "admin",
|
||||||
"password": null
|
"password": "admin"
|
||||||
},
|
},
|
||||||
"notes": [
|
"notes": []
|
||||||
{
|
|
||||||
"text": "After installation, the admin user credentials are saved in the file ~/librenms.creds inside the container.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,6 @@
|
|||||||
{
|
{
|
||||||
"text": "The integrated daemon config is located at `/root/.config/daemon/config.json`",
|
"text": "The integrated daemon config is located at `/root/.config/daemon/config.json`",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "When using a reverse proxy, edit `/opt/netvisor/ui/build/_app/env.js`: add 443 to `PUBLIC_SERVER_PORT` and remove 'default' from `PUBLIC_SERVER_HOSTNAME`.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
"ram": 3072,
|
"ram": 3072,
|
||||||
"hdd": 8,
|
"hdd": 8,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "OPNsense",
|
|
||||||
"slug": "opnsense-vm",
|
|
||||||
"categories": [
|
|
||||||
4,
|
|
||||||
2
|
|
||||||
],
|
|
||||||
"date_created": "2025-11-23",
|
|
||||||
"type": "vm",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 443,
|
|
||||||
"documentation": "https://docs.opnsense.org/",
|
|
||||||
"website": "https://opnsense.org/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/opnsense.webp",
|
|
||||||
"config_path": "",
|
|
||||||
"description": "OPNsense is an open-source firewall and routing platform based on FreeBSD. It provides advanced security features, including intrusion detection, VPN support, traffic shaping, and web filtering, with an intuitive web interface for easy management. Known for its reliability and regular updates, OPNsense is a popular choice for both businesses and home networks.",
|
|
||||||
"disable": true,
|
|
||||||
"disable_description": "This script has been temporarily disabled due to installation failures. The OPNsense bootstrap process was not completing successfully, resulting in a plain FreeBSD VM instead of a functional OPNsense installation. The issue is being investigated and the script will be re-enabled once resolved. For more details, see: https://github.com/community-scripts/ProxmoxVE/issues/6183",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "vm/opnsense-vm.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 4,
|
|
||||||
"ram": 8192,
|
|
||||||
"hdd": 10,
|
|
||||||
"os": "FreeBSD",
|
|
||||||
"version": "latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": "root",
|
|
||||||
"password": "opnsense"
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "It will fail with default settings if there is no vmbr0 and vmbr1 on your node. Use advanced settings in this case.",
|
|
||||||
"type": "warning"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"categories": [
|
"categories": [
|
||||||
6
|
6
|
||||||
],
|
],
|
||||||
"date_created": "2025-11-17",
|
"date_created": "2025-09-04",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
{
|
{
|
||||||
"text": "Type `cat ~/passbolt.creds` to see MariaDB database credentials. You will need those to setup Passbolt.",
|
"text": "Type `cat ~/.Passbolt.creds` to see MariaDB database credentials. You will need those to setup Passbolt.",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
],
|
],
|
||||||
"date_created": "2025-08-26",
|
"date_created": "2025-08-26",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": false,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 8888,
|
"interface_port": 8888,
|
||||||
"documentation": "https://docs.searxng.org/",
|
"documentation": "https://docs.searxng.org/",
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Upgopher",
|
|
||||||
"slug": "upgopher",
|
|
||||||
"categories": [
|
|
||||||
11
|
|
||||||
],
|
|
||||||
"date_created": "2025-11-22",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 9090,
|
|
||||||
"documentation": "https://github.com/wanetty/upgopher#readme",
|
|
||||||
"config_path": "",
|
|
||||||
"website": "https://github.com/wanetty/upgopher",
|
|
||||||
"logo": "https://raw.githubusercontent.com/wanetty/upgopher/main/static/logopher.webp",
|
|
||||||
"description": "A simple Go web server for file upload, download, and browsing. Cross-platform alternative to Python-based file servers with no library dependencies. Features file upload via web interface, directory navigation, URL copying to clipboard, optional basic authentication, HTTPS support, and hidden files toggle.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/upgopher.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 1,
|
|
||||||
"ram": 512,
|
|
||||||
"hdd": 4,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "Default uploads directory: `/opt/upgopher/uploads`",
|
|
||||||
"type": "info"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "Set application startup options by editing `/etc/systemd/system/upgopher.service`. Read documentation for available options.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,67 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import React, { useEffect, useState } from "react";
|
||||||
ArrowUpDown,
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
Box,
|
|
||||||
CheckCircle2,
|
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
List,
|
|
||||||
Loader2,
|
|
||||||
Trophy,
|
|
||||||
XCircle,
|
|
||||||
} from "lucide-react";
|
|
||||||
import {
|
|
||||||
Bar,
|
|
||||||
BarChart,
|
|
||||||
CartesianGrid,
|
|
||||||
Cell,
|
|
||||||
LabelList,
|
|
||||||
XAxis,
|
|
||||||
} from "recharts";
|
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
|
||||||
|
|
||||||
import type { ChartConfig } from "@/components/ui/chart";
|
import ApplicationChart from "../../components/application-chart";
|
||||||
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableBody,
|
|
||||||
TableCell,
|
|
||||||
TableHead,
|
|
||||||
TableHeader,
|
|
||||||
TableRow,
|
|
||||||
} from "@/components/ui/table";
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle,
|
|
||||||
} from "@/components/ui/card";
|
|
||||||
import {
|
|
||||||
ChartContainer,
|
|
||||||
ChartTooltip,
|
|
||||||
ChartTooltipContent,
|
|
||||||
} from "@/components/ui/chart";
|
|
||||||
import { formattedBadge } from "@/components/command-menu";
|
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
|
|
||||||
type DataModel = {
|
type DataModel = {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -88,76 +30,42 @@ type SummaryData = {
|
|||||||
nsapp_count: Record<string, number>;
|
nsapp_count: Record<string, number>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Chart colors optimized for both light and dark modes
|
const DataFetcher: React.FC = () => {
|
||||||
// Medium-toned colors that are visible and not too flashy in both themes
|
|
||||||
const CHART_COLORS = [
|
|
||||||
"#5B8DEF", // blue - medium tone
|
|
||||||
"#4ECDC4", // teal - medium tone
|
|
||||||
"#FF8C42", // orange - medium tone
|
|
||||||
"#A78BFA", // purple - medium tone
|
|
||||||
"#F472B6", // pink - medium tone
|
|
||||||
"#38BDF8", // cyan - medium tone
|
|
||||||
"#4ADE80", // green - medium tone
|
|
||||||
"#FBBF24", // yellow - medium tone
|
|
||||||
"#818CF8", // indigo - medium tone
|
|
||||||
"#FB7185", // rose - medium tone
|
|
||||||
"#2DD4BF", // turquoise - medium tone
|
|
||||||
"#C084FC", // violet - medium tone
|
|
||||||
"#60A5FA", // sky blue - medium tone
|
|
||||||
"#84CC16", // lime - medium tone
|
|
||||||
"#F59E0B", // amber - medium tone
|
|
||||||
"#A855F7", // purple - medium tone
|
|
||||||
"#10B981", // emerald - medium tone
|
|
||||||
"#EAB308", // gold - medium tone
|
|
||||||
"#3B82F6", // royal blue - medium tone
|
|
||||||
"#EF4444", // red - medium tone
|
|
||||||
];
|
|
||||||
|
|
||||||
const chartConfigApps = {
|
|
||||||
count: {
|
|
||||||
label: "Installations",
|
|
||||||
color: "hsl(var(--chart-1))",
|
|
||||||
},
|
|
||||||
} satisfies ChartConfig;
|
|
||||||
|
|
||||||
export default function DataPage() {
|
|
||||||
const [data, setData] = useState<DataModel[]>([]);
|
const [data, setData] = useState<DataModel[]>([]);
|
||||||
const [summary, setSummary] = useState<SummaryData | null>(null);
|
const [summary, setSummary] = useState<SummaryData | null>(null);
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [itemsPerPage, setItemsPerPage] = useState(25);
|
const [itemsPerPage, setItemsPerPage] = useState(25);
|
||||||
const [sortConfig, setSortConfig] = useState<{
|
const [sortConfig, setSortConfig] = useState<{ key: string; direction: "ascending" | "descending" } | null>(null);
|
||||||
key: string;
|
|
||||||
direction: "ascending" | "descending";
|
|
||||||
} | null>(null);
|
|
||||||
|
|
||||||
const nf = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
|
const nf = new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchSummary = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("https://api.htl-braunau.at/data/summary");
|
||||||
|
if (!response.ok)
|
||||||
|
throw new Error(`Failed to fetch summary: ${response.statusText}`);
|
||||||
|
const result: SummaryData = await response.json();
|
||||||
|
setSummary(result);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
setError((err as Error).message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchSummary();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchPaginatedData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const [summaryRes, dataRes] = await Promise.all([
|
const response = await fetch(`https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? "" : itemsPerPage}`);
|
||||||
fetch("https://api.htl-braunau.at/data/summary"),
|
if (!response.ok)
|
||||||
fetch(
|
throw new Error(`Failed to fetch data: ${response.statusText}`);
|
||||||
`https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? "" : itemsPerPage
|
const result: DataModel[] = await response.json();
|
||||||
}`,
|
setData(result);
|
||||||
),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!summaryRes.ok) {
|
|
||||||
throw new Error(`Failed to fetch summary: ${summaryRes.statusText}`);
|
|
||||||
}
|
|
||||||
if (!dataRes.ok) {
|
|
||||||
throw new Error(`Failed to fetch data: ${dataRes.statusText}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const summaryData: SummaryData = await summaryRes.json();
|
|
||||||
const pageData: DataModel[] = await dataRes.json();
|
|
||||||
|
|
||||||
setSummary(summaryData);
|
|
||||||
setData(pageData);
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
setError((err as Error).message);
|
setError((err as Error).message);
|
||||||
@@ -167,13 +75,13 @@ export default function DataPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchData();
|
fetchPaginatedData();
|
||||||
}, [currentPage, itemsPerPage]);
|
}, [currentPage, itemsPerPage]);
|
||||||
|
|
||||||
const sortedData = useMemo(() => {
|
const sortedData = React.useMemo(() => {
|
||||||
if (!sortConfig)
|
if (!sortConfig)
|
||||||
return data;
|
return data;
|
||||||
return [...data].sort((a, b) => {
|
const sorted = [...data].sort((a, b) => {
|
||||||
if (a[sortConfig.key] < b[sortConfig.key]) {
|
if (a[sortConfig.key] < b[sortConfig.key]) {
|
||||||
return sortConfig.direction === "ascending" ? -1 : 1;
|
return sortConfig.direction === "ascending" ? -1 : 1;
|
||||||
}
|
}
|
||||||
@@ -182,15 +90,23 @@ export default function DataPage() {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
return sorted;
|
||||||
}, [data, sortConfig]);
|
}, [data, sortConfig]);
|
||||||
|
|
||||||
|
if (loading)
|
||||||
|
return <p>Loading...</p>;
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<p>
|
||||||
|
Error:
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const requestSort = (key: string) => {
|
const requestSort = (key: string) => {
|
||||||
let direction: "ascending" | "descending" = "ascending";
|
let direction: "ascending" | "descending" = "ascending";
|
||||||
if (
|
if (sortConfig && sortConfig.key === key && sortConfig.direction === "ascending") {
|
||||||
sortConfig
|
|
||||||
&& sortConfig.key === key
|
|
||||||
&& sortConfig.direction === "ascending"
|
|
||||||
) {
|
|
||||||
direction = "descending";
|
direction = "descending";
|
||||||
}
|
}
|
||||||
setSortConfig({ key, direction });
|
setSortConfig({ key, direction });
|
||||||
@@ -198,447 +114,135 @@ export default function DataPage() {
|
|||||||
|
|
||||||
const formatDate = (dateString: string): string => {
|
const formatDate = (dateString: string): string => {
|
||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
return new Intl.DateTimeFormat("en-US", {
|
const year = date.getFullYear();
|
||||||
dateStyle: "medium",
|
const month = date.getMonth() + 1;
|
||||||
timeStyle: "short",
|
const day = date.getDate();
|
||||||
}).format(date);
|
const hours = String(date.getHours()).padStart(2, "0");
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
const timezoneOffset = dateString.slice(-6);
|
||||||
|
return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTypeBadge = (type: string) => {
|
|
||||||
if (type === "lxc")
|
|
||||||
return formattedBadge("ct");
|
|
||||||
if (type === "vm")
|
|
||||||
return formattedBadge("vm");
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Stats calculations
|
|
||||||
const successCount = summary?.status_count.done ?? 0;
|
|
||||||
const failureCount = summary?.status_count.failed ?? 0;
|
|
||||||
const totalCount = summary?.total_entries ?? 0;
|
|
||||||
const successRate = totalCount > 0 ? (successCount / totalCount) * 100 : 0;
|
|
||||||
|
|
||||||
const allApps = useMemo(() => {
|
|
||||||
if (!summary?.nsapp_count)
|
|
||||||
return [];
|
|
||||||
return Object.entries(summary.nsapp_count).sort(([, a], [, b]) => b - a);
|
|
||||||
}, [summary]);
|
|
||||||
|
|
||||||
const topApps = useMemo(() => {
|
|
||||||
return allApps.slice(0, 15);
|
|
||||||
}, [allApps]);
|
|
||||||
|
|
||||||
const mostPopularApp = topApps[0];
|
|
||||||
|
|
||||||
// Chart Data
|
|
||||||
const appsChartData = topApps.map(([name, count], index) => ({
|
|
||||||
app: name,
|
|
||||||
count,
|
|
||||||
fill: CHART_COLORS[index % CHART_COLORS.length],
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<div className="p-6 text-center text-red-500">
|
|
||||||
<p>
|
|
||||||
Error loading data:
|
|
||||||
{error}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-3">
|
<div className="p-6 mt-20">
|
||||||
<div className="mt-20 flex sm:px-4 xl:px-0">
|
<h1 className="text-2xl font-bold mb-4 text-center">Created LXCs</h1>
|
||||||
<div className="mx-4 w-full sm:mx-0 space-y-8">
|
<ApplicationChart data={summary} />
|
||||||
{/* Header */}
|
<p className="text-lg font-bold mt-4"> </p>
|
||||||
<div>
|
<div className="mb-4 flex justify-between items-center">
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Analytics</h1>
|
<p className="text-lg font-bold">
|
||||||
<p className="text-muted-foreground">
|
{nf.format(
|
||||||
Overview of container installations and system statistics.
|
summary?.total_entries ?? 0,
|
||||||
</p>
|
)}
|
||||||
</div>
|
{" "}
|
||||||
|
results found
|
||||||
{/* Widgets */}
|
</p>
|
||||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
<p className="text-lg font">
|
||||||
<Card>
|
Status Legend: 🔄 installing
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
{" "}
|
||||||
<CardTitle className="text-sm font-medium">Total Created</CardTitle>
|
{nf.format(summary?.status_count.installing ?? 0)}
|
||||||
<Box className="h-4 w-4 text-muted-foreground" />
|
{" "}
|
||||||
</CardHeader>
|
| ✔️ completed
|
||||||
<CardContent>
|
{" "}
|
||||||
<div className="text-2xl font-bold">{nf.format(totalCount)}</div>
|
{nf.format(summary?.status_count.done ?? 0)}
|
||||||
<p className="text-xs text-muted-foreground">
|
{" "}
|
||||||
Total LXC/VM entries found
|
| ❌ failed
|
||||||
</p>
|
{" "}
|
||||||
</CardContent>
|
{nf.format(summary?.status_count.failed ?? 0)}
|
||||||
</Card>
|
{" "}
|
||||||
|
| ❓ unknown
|
||||||
<Card>
|
</p>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
</div>
|
||||||
<CardTitle className="text-sm font-medium">Success Rate</CardTitle>
|
<div className="overflow-x-auto">
|
||||||
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
<div className="overflow-y-auto lg:overflow-y-visible">
|
||||||
</CardHeader>
|
<table className="min-w-full table-auto border-collapse">
|
||||||
<CardContent>
|
<thead>
|
||||||
<div className="text-2xl font-bold">
|
<tr>
|
||||||
{successRate.toFixed(1)}
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("status")}>Status</th>
|
||||||
%
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("type")}>Type</th>
|
||||||
</div>
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("nsapp")}>Application</th>
|
||||||
<p className="text-xs text-muted-foreground">
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("os_type")}>OS</th>
|
||||||
{nf.format(successCount)}
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("os_version")}>OS Version</th>
|
||||||
{" "}
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("disk_size")}>Disk Size</th>
|
||||||
successful installations
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("core_count")}>Core Count</th>
|
||||||
</p>
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("ram_size")}>RAM Size</th>
|
||||||
</CardContent>
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("method")}>Method</th>
|
||||||
</Card>
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("pve_version")}>PVE Version</th>
|
||||||
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("error")}>Error Message</th>
|
||||||
<Card>
|
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort("created_at")}>Created At</th>
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
</tr>
|
||||||
<CardTitle className="text-sm font-medium">Failures</CardTitle>
|
</thead>
|
||||||
<XCircle className="h-4 w-4 text-red-500" />
|
<tbody>
|
||||||
</CardHeader>
|
{sortedData.map((item, index) => (
|
||||||
<CardContent>
|
<tr key={index}>
|
||||||
<div className="text-2xl font-bold">{nf.format(failureCount)}</div>
|
<td className="px-4 py-2 border-b">
|
||||||
<p className="text-xs text-muted-foreground">
|
{item.status === "done"
|
||||||
Installations encountered errors
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
||||||
<CardTitle className="text-sm font-medium">Most Popular</CardTitle>
|
|
||||||
<Trophy className="h-4 w-4 text-yellow-500" />
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="truncate text-2xl font-bold">
|
|
||||||
{mostPopularApp ? mostPopularApp[0] : "N/A"}
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-muted-foreground">
|
|
||||||
{mostPopularApp ? nf.format(mostPopularApp[1]) : 0}
|
|
||||||
{" "}
|
|
||||||
installations
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Graphs */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between">
|
|
||||||
<div className="space-y-1.5">
|
|
||||||
<CardTitle>Top Applications</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
The most frequently installed applications.
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button variant="outline" size="sm" className="ml-auto">
|
|
||||||
<List className="mr-2 h-4 w-4" />
|
|
||||||
View All
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="max-h-[80vh] sm:max-w-md">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Application Statistics</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Installation counts for all
|
|
||||||
{" "}
|
|
||||||
{allApps.length}
|
|
||||||
{" "}
|
|
||||||
applications.
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
<ScrollArea className="h-[60vh] w-full rounded-md border p-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
{allApps.map(([name, count], index) => (
|
|
||||||
<div
|
|
||||||
key={name}
|
|
||||||
className="flex items-center justify-between text-sm"
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<span className="w-8 font-mono text-muted-foreground">
|
|
||||||
{index + 1}
|
|
||||||
.
|
|
||||||
</span>
|
|
||||||
<span className="font-medium">{name}</span>
|
|
||||||
</div>
|
|
||||||
<span className="font-mono">{nf.format(count)}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="pl-2">
|
|
||||||
<div className="h-[300px] w-full">
|
|
||||||
{loading
|
|
||||||
? (
|
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
|
||||||
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
<ChartContainer config={chartConfigApps} className="h-full w-full">
|
|
||||||
<BarChart
|
|
||||||
accessibilityLayer
|
|
||||||
data={appsChartData}
|
|
||||||
margin={{
|
|
||||||
top: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CartesianGrid vertical={false} />
|
|
||||||
<XAxis
|
|
||||||
dataKey="app"
|
|
||||||
tickLine={false}
|
|
||||||
tickMargin={10}
|
|
||||||
axisLine={false}
|
|
||||||
tickFormatter={value => (value.length > 8 ? `${value.slice(0, 8)}...` : value)}
|
|
||||||
/>
|
|
||||||
<ChartTooltip
|
|
||||||
cursor={false}
|
|
||||||
content={<ChartTooltipContent nameKey="app" />}
|
|
||||||
/>
|
|
||||||
<Bar dataKey="count" radius={8}>
|
|
||||||
{appsChartData.map((entry, index) => (
|
|
||||||
<Cell key={`cell-${index}`} fill={entry.fill} />
|
|
||||||
))}
|
|
||||||
<LabelList
|
|
||||||
position="top"
|
|
||||||
offset={12}
|
|
||||||
className="fill-foreground"
|
|
||||||
fontSize={12}
|
|
||||||
/>
|
|
||||||
</Bar>
|
|
||||||
</BarChart>
|
|
||||||
</ChartContainer>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* Data Table */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<CardTitle>Installation Log</CardTitle>
|
|
||||||
<CardDescription>
|
|
||||||
Detailed records of all container creation attempts.
|
|
||||||
</CardDescription>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Select
|
|
||||||
value={String(itemsPerPage)}
|
|
||||||
onValueChange={val => setItemsPerPage(Number(val))}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[80px]">
|
|
||||||
<SelectValue placeholder="Limit" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="10">10</SelectItem>
|
|
||||||
<SelectItem value="25">25</SelectItem>
|
|
||||||
<SelectItem value="50">50</SelectItem>
|
|
||||||
<SelectItem value="100">100</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="rounded-md border">
|
|
||||||
<Table>
|
|
||||||
<TableHeader>
|
|
||||||
<TableRow>
|
|
||||||
<TableHead
|
|
||||||
className="w-[100px] cursor-pointer"
|
|
||||||
onClick={() => requestSort("status")}
|
|
||||||
>
|
|
||||||
Status
|
|
||||||
{sortConfig?.key === "status" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => requestSort("type")}
|
|
||||||
>
|
|
||||||
Type
|
|
||||||
{sortConfig?.key === "type" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => requestSort("nsapp")}
|
|
||||||
>
|
|
||||||
Application
|
|
||||||
{sortConfig?.key === "nsapp" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="hidden cursor-pointer md:table-cell"
|
|
||||||
onClick={() => requestSort("os_type")}
|
|
||||||
>
|
|
||||||
OS
|
|
||||||
{sortConfig?.key === "os_type" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="hidden cursor-pointer md:table-cell"
|
|
||||||
onClick={() => requestSort("disk_size")}
|
|
||||||
>
|
|
||||||
Disk Size
|
|
||||||
{sortConfig?.key === "disk_size" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="hidden cursor-pointer lg:table-cell"
|
|
||||||
onClick={() => requestSort("core_count")}
|
|
||||||
>
|
|
||||||
Core Count
|
|
||||||
{sortConfig?.key === "core_count" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="hidden cursor-pointer lg:table-cell"
|
|
||||||
onClick={() => requestSort("ram_size")}
|
|
||||||
>
|
|
||||||
RAM Size
|
|
||||||
{sortConfig?.key === "ram_size" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
<TableHead
|
|
||||||
className="cursor-pointer text-right"
|
|
||||||
onClick={() => requestSort("created_at")}
|
|
||||||
>
|
|
||||||
Created At
|
|
||||||
{sortConfig?.key === "created_at" && (
|
|
||||||
<ArrowUpDown className="ml-2 inline h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{loading
|
|
||||||
? (
|
? (
|
||||||
<TableRow>
|
"✔️"
|
||||||
<TableCell colSpan={8} className="h-24 text-center">
|
|
||||||
<div className="flex items-center justify-center gap-2">
|
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
|
||||||
{" "}
|
|
||||||
Loading data...
|
|
||||||
</div>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)
|
)
|
||||||
: sortedData.length > 0
|
: item.status === "failed"
|
||||||
? (
|
? (
|
||||||
sortedData.map((item, idx) => (
|
"❌"
|
||||||
<TableRow key={`${item.id}-${idx}`}>
|
)
|
||||||
<TableCell>
|
: item.status === "installing"
|
||||||
{item.status === "done"
|
? (
|
||||||
? (
|
"🔄"
|
||||||
<Badge className="text-green-500/75 border-green-500/75">
|
)
|
||||||
Success
|
: (
|
||||||
</Badge>
|
item.status
|
||||||
)
|
)}
|
||||||
: item.status === "failed"
|
</td>
|
||||||
? (
|
<td className="px-4 py-2 border-b">
|
||||||
<Badge className="text-red-500/75 border-red-500/75">
|
{item.type === "lxc"
|
||||||
Failed
|
? (
|
||||||
</Badge>
|
"📦"
|
||||||
)
|
)
|
||||||
: item.status === "installing"
|
: item.type === "vm"
|
||||||
? (
|
? (
|
||||||
<Badge className="text-blue-500/75 border-blue-500/75">
|
"🖥️"
|
||||||
Installing
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
: (
|
|
||||||
<Badge variant="outline">
|
|
||||||
{item.status}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{getTypeBadge(item.type) || (
|
|
||||||
<Badge variant="outline">
|
|
||||||
{item.type}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="font-medium">
|
|
||||||
{item.nsapp}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="hidden md:table-cell">
|
|
||||||
{item.os_type}
|
|
||||||
{" "}
|
|
||||||
{item.os_version}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="hidden md:table-cell">
|
|
||||||
{item.disk_size}
|
|
||||||
MB
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="hidden lg:table-cell">
|
|
||||||
{item.core_count}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="hidden lg:table-cell">
|
|
||||||
{item.ram_size}
|
|
||||||
MB
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="text-right">
|
|
||||||
{formatDate(item.created_at)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
)
|
)
|
||||||
: (
|
: (
|
||||||
<TableRow>
|
item.type
|
||||||
<TableCell colSpan={8} className="h-24 text-center">
|
|
||||||
No results found.
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)}
|
)}
|
||||||
</TableBody>
|
</td>
|
||||||
</Table>
|
<td className="px-4 py-2 border-b">{item.nsapp}</td>
|
||||||
</div>
|
<td className="px-4 py-2 border-b">{item.os_type}</td>
|
||||||
|
<td className="px-4 py-2 border-b">{item.os_version}</td>
|
||||||
<div className="flex items-center justify-end space-x-2 py-4">
|
<td className="px-4 py-2 border-b">{item.disk_size}</td>
|
||||||
<Button
|
<td className="px-4 py-2 border-b">{item.core_count}</td>
|
||||||
variant="outline"
|
<td className="px-4 py-2 border-b">{item.ram_size}</td>
|
||||||
size="sm"
|
<td className="px-4 py-2 border-b">{item.method}</td>
|
||||||
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
|
<td className="px-4 py-2 border-b">{item.pve_version}</td>
|
||||||
disabled={currentPage === 1 || loading}
|
<td className="px-4 py-2 border-b">{item.error}</td>
|
||||||
>
|
<td className="px-4 py-2 border-b">{formatDate(item.created_at)}</td>
|
||||||
<ChevronLeft className="mr-2 h-4 w-4" />
|
</tr>
|
||||||
Previous
|
))}
|
||||||
</Button>
|
</tbody>
|
||||||
<div className="text-sm text-muted-foreground">
|
</table>
|
||||||
Page
|
|
||||||
{" "}
|
|
||||||
{currentPage}
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setCurrentPage(prev => prev + 1)}
|
|
||||||
disabled={loading || sortedData.length < itemsPerPage}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
<ChevronRight className="ml-2 h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mt-4 flex justify-between items-center">
|
||||||
|
<button onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))} disabled={currentPage === 1} className="p-2 border">Previous</button>
|
||||||
|
<span>
|
||||||
|
Page
|
||||||
|
{currentPage}
|
||||||
|
</span>
|
||||||
|
<button onClick={() => setCurrentPage(prev => prev + 1)} className="p-2 border">Next</button>
|
||||||
|
<select
|
||||||
|
value={itemsPerPage}
|
||||||
|
onChange={e => setItemsPerPage(Number(e.target.value))}
|
||||||
|
className="p-2 border"
|
||||||
|
>
|
||||||
|
<option value={10}>10</option>
|
||||||
|
<option value={20}>20</option>
|
||||||
|
<option value={50}>50</option>
|
||||||
|
<option value={100}>100</option>
|
||||||
|
<option value={250}>250</option>
|
||||||
|
<option value={500}>500</option>
|
||||||
|
<option value={5000}>5000</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default DataFetcher;
|
||||||
|
|||||||
@@ -35,22 +35,12 @@ export const ScriptSchema = z.object({
|
|||||||
logo: z.string().url().nullable(),
|
logo: z.string().url().nullable(),
|
||||||
config_path: z.string(),
|
config_path: z.string(),
|
||||||
description: z.string().min(1, "Description is required"),
|
description: z.string().min(1, "Description is required"),
|
||||||
disable: z.boolean().optional(),
|
|
||||||
disable_description: z.string().optional(),
|
|
||||||
install_methods: z.array(InstallMethodSchema).min(1, "At least one install method is required"),
|
install_methods: z.array(InstallMethodSchema).min(1, "At least one install method is required"),
|
||||||
default_credentials: z.object({
|
default_credentials: z.object({
|
||||||
username: z.string().nullable(),
|
username: z.string().nullable(),
|
||||||
password: z.string().nullable(),
|
password: z.string().nullable(),
|
||||||
}),
|
}),
|
||||||
notes: z.array(NoteSchema),
|
notes: z.array(NoteSchema),
|
||||||
}).refine((data) => {
|
|
||||||
if (data.disable === true && !data.disable_description) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}, {
|
|
||||||
message: "disable_description is required when disable is true",
|
|
||||||
path: ["disable_description"],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type Script = z.infer<typeof ScriptSchema>;
|
export type Script = z.infer<typeof ScriptSchema>;
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ const initialScript: Script = {
|
|||||||
website: null,
|
website: null,
|
||||||
logo: null,
|
logo: null,
|
||||||
description: "",
|
description: "",
|
||||||
disable: undefined,
|
|
||||||
disable_description: undefined,
|
|
||||||
install_methods: [],
|
install_methods: [],
|
||||||
default_credentials: {
|
default_credentials: {
|
||||||
username: null,
|
username: null,
|
||||||
@@ -263,25 +261,7 @@ export default function JSONGenerator() {
|
|||||||
<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">
|
|
||||||
<Switch checked={script.disable || false} onCheckedChange={checked => updateScript("disable", checked)} />
|
|
||||||
<label>Disabled</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{script.disable && (
|
|
||||||
<div>
|
|
||||||
<Label>
|
|
||||||
Disable Description
|
|
||||||
{" "}
|
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</Label>
|
|
||||||
<Textarea
|
|
||||||
placeholder="Explain why this script is disabled..."
|
|
||||||
value={script.disable_description || ""}
|
|
||||||
onChange={e => updateScript("disable_description", e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<Input
|
<Input
|
||||||
placeholder="Interface Port"
|
placeholder="Interface Port"
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { basePath } from "@/config/site-config";
|
|
||||||
|
|
||||||
export default function NotFoundPage() {
|
export default function NotFoundPage() {
|
||||||
return (
|
return (
|
||||||
@@ -13,17 +12,7 @@ export default function NotFoundPage() {
|
|||||||
Oops, the page you are looking for could not be found.
|
Oops, the page you are looking for could not be found.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button onClick={() => window.history.back()} variant="secondary">
|
||||||
onClick={() => {
|
|
||||||
if (window.history.length > 1) {
|
|
||||||
window.history.back();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.location.href = `/${basePath}`;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
variant="secondary"
|
|
||||||
>
|
|
||||||
Go Back
|
Go Back
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export default function ScriptAccordion({
|
|||||||
className={`flex cursor-pointer items-center justify-between gap-1 px-1 py-1 text-muted-foreground hover:rounded-lg hover:bg-accent/60 hover:dark:bg-accent/20 ${selectedScript === script.slug
|
className={`flex cursor-pointer items-center justify-between gap-1 px-1 py-1 text-muted-foreground hover:rounded-lg hover:bg-accent/60 hover:dark:bg-accent/20 ${selectedScript === script.slug
|
||||||
? "rounded-lg bg-accent font-semibold dark:bg-accent/30 dark:text-white"
|
? "rounded-lg bg-accent font-semibold dark:bg-accent/30 dark:text-white"
|
||||||
: ""
|
: ""
|
||||||
} ${script.disable ? "opacity-60" : ""}`}
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSelected(script.slug);
|
handleSelected(script.slug);
|
||||||
setSelectedCategory(category.name);
|
setSelectedCategory(category.name);
|
||||||
@@ -143,9 +143,7 @@ export default function ScriptAccordion({
|
|||||||
alt={script.name}
|
alt={script.name}
|
||||||
className="mr-1 w-4 h-4 rounded-full"
|
className="mr-1 w-4 h-4 rounded-full"
|
||||||
/>
|
/>
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">{script.name}</span>
|
||||||
{script.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{formattedBadge(script.type)}
|
{formattedBadge(script.type)}
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { useVersions } from "@/hooks/use-versions";
|
|||||||
import { basePath } from "@/config/site-config";
|
import { basePath } from "@/config/site-config";
|
||||||
import { extractDate } from "@/lib/time";
|
import { extractDate } from "@/lib/time";
|
||||||
|
|
||||||
import DisableDescription from "./script-items/disable-description";
|
|
||||||
import { getDisplayValueFromType } from "./script-info-blocks";
|
import { getDisplayValueFromType } from "./script-info-blocks";
|
||||||
import DefaultPassword from "./script-items/default-password";
|
import DefaultPassword from "./script-items/default-password";
|
||||||
import InstallCommand from "./script-items/install-command";
|
import InstallCommand from "./script-items/install-command";
|
||||||
@@ -147,45 +146,37 @@ export function ScriptItem({ item, setSelectedScript }: ScriptItemProps) {
|
|||||||
<ScriptHeader item={item} />
|
<ScriptHeader item={item} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
{item.disable && item.disable_description && (
|
<Description item={item} />
|
||||||
<DisableDescription item={item} />
|
<Alerts item={item} />
|
||||||
) }
|
|
||||||
|
|
||||||
{!item.disable && (
|
<div className="mt-4 rounded-lg border shadow-sm">
|
||||||
<>
|
<div className="flex gap-3 px-4 py-2 bg-accent/25">
|
||||||
<Description item={item} />
|
<h2 className="text-lg font-semibold">
|
||||||
|
How to
|
||||||
<Alerts item={item} />
|
{" "}
|
||||||
<div className="mt-4 rounded-lg border shadow-sm">
|
{item.type === "pve" ? "use" : item.type === "addon" ? "apply" : "install"}
|
||||||
|
</h2>
|
||||||
|
<Tooltips item={item} />
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<div className="">
|
||||||
|
<InstallCommand item={item} />
|
||||||
|
</div>
|
||||||
|
{item.config_path && (
|
||||||
|
<>
|
||||||
|
<Separator />
|
||||||
<div className="flex gap-3 px-4 py-2 bg-accent/25">
|
<div className="flex gap-3 px-4 py-2 bg-accent/25">
|
||||||
<h2 className="text-lg font-semibold">
|
<h2 className="text-lg font-semibold">Location of config file</h2>
|
||||||
How to
|
|
||||||
{" "}
|
|
||||||
{item.type === "pve" ? "use" : item.type === "addon" ? "apply" : "install"}
|
|
||||||
</h2>
|
|
||||||
<Tooltips item={item} />
|
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="">
|
<div className="">
|
||||||
<InstallCommand item={item} />
|
<ConfigFile configPath={item.config_path} />
|
||||||
</div>
|
</div>
|
||||||
{item.config_path && (
|
</>
|
||||||
<>
|
)}
|
||||||
<Separator />
|
</div>
|
||||||
<div className="flex gap-3 px-4 py-2 bg-accent/25">
|
|
||||||
<h2 className="text-lg font-semibold">Location of config file</h2>
|
|
||||||
</div>
|
|
||||||
<Separator />
|
|
||||||
<div className="">
|
|
||||||
<ConfigFile configPath={item.config_path} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DefaultPassword item={item} />
|
<DefaultPassword item={item} />
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { AlertCircle } from "lucide-react";
|
|
||||||
|
|
||||||
import type { Script } from "@/lib/types";
|
|
||||||
|
|
||||||
import TextParseLinks from "@/components/text-parse-links";
|
|
||||||
import { AlertColors } from "@/config/site-config";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
export default function DisableDescription({ item }: { item: Script }) {
|
|
||||||
return (
|
|
||||||
<div className="mt-4 flex flex-col shadow-sm gap-2">
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"flex items-start gap-3 rounded-lg border p-4 text-sm",
|
|
||||||
AlertColors.warning,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<AlertCircle className="h-5 min-h-5 w-5 min-w-5 mt-0.5" />
|
|
||||||
<div className="flex flex-col gap-2">
|
|
||||||
<h3 className="font-semibold text-base">Script Disabled</h3>
|
|
||||||
<p>{TextParseLinks(item.disable_description!)}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
199
frontend/src/components/application-chart.tsx
Normal file
199
frontend/src/components/application-chart.tsx
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ArcElement, Chart as ChartJS, Tooltip as ChartTooltip, Legend } from "chart.js";
|
||||||
|
import ChartDataLabels from "chartjs-plugin-datalabels";
|
||||||
|
import { BarChart3, PieChart } from "lucide-react";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Pie } from "react-chartjs-2";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
ChartJS.register(ArcElement, ChartTooltip, Legend, ChartDataLabels);
|
||||||
|
|
||||||
|
type SummaryData = {
|
||||||
|
nsapp_count: Record<string, number>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ApplicationChartProps = {
|
||||||
|
data: SummaryData | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ITEMS_PER_PAGE = 20;
|
||||||
|
const CHART_COLORS = [
|
||||||
|
"#ff6384",
|
||||||
|
"#36a2eb",
|
||||||
|
"#ffce56",
|
||||||
|
"#4bc0c0",
|
||||||
|
"#9966ff",
|
||||||
|
"#ff9f40",
|
||||||
|
"#4dc9f6",
|
||||||
|
"#f67019",
|
||||||
|
"#537bc4",
|
||||||
|
"#acc236",
|
||||||
|
"#166a8f",
|
||||||
|
"#00a950",
|
||||||
|
"#58595b",
|
||||||
|
"#8549ba",
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ApplicationChart({ data }: ApplicationChartProps) {
|
||||||
|
const [isChartOpen, setIsChartOpen] = useState(false);
|
||||||
|
const [isTableOpen, setIsTableOpen] = useState(false);
|
||||||
|
const [chartStartIndex, setChartStartIndex] = useState(0);
|
||||||
|
const [tableLimit, setTableLimit] = useState(ITEMS_PER_PAGE);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const sortedApps = Object.entries(data.nsapp_count)
|
||||||
|
.sort(([, a], [, b]) => b - a);
|
||||||
|
|
||||||
|
const chartApps = sortedApps.slice(
|
||||||
|
chartStartIndex,
|
||||||
|
chartStartIndex + ITEMS_PER_PAGE,
|
||||||
|
);
|
||||||
|
|
||||||
|
const chartData = {
|
||||||
|
labels: chartApps.map(([name]) => name),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: chartApps.map(([, count]) => count),
|
||||||
|
backgroundColor: CHART_COLORS,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const chartOptions = {
|
||||||
|
plugins: {
|
||||||
|
legend: { display: false },
|
||||||
|
datalabels: {
|
||||||
|
color: "white",
|
||||||
|
font: { weight: "bold" as const },
|
||||||
|
formatter: (value: number, context: any) => {
|
||||||
|
const label = context.chart.data.labels?.[context.dataIndex];
|
||||||
|
return `${label}\n(${value})`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-6 flex justify-center gap-4">
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setIsChartOpen(true)}
|
||||||
|
>
|
||||||
|
<PieChart className="h-5 w-5" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Open Chart View</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setIsTableOpen(true)}
|
||||||
|
>
|
||||||
|
<BarChart3 className="h-5 w-5" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>Open Table View</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
|
||||||
|
<Dialog open={isChartOpen} onOpenChange={setIsChartOpen}>
|
||||||
|
<DialogContent className="max-w-3xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Applications Distribution</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="h-[60vh] w-full">
|
||||||
|
<Pie data={chartData} options={chartOptions} />
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center gap-4">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - ITEMS_PER_PAGE))}
|
||||||
|
disabled={chartStartIndex === 0}
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
{" "}
|
||||||
|
{ITEMS_PER_PAGE}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setChartStartIndex(chartStartIndex + ITEMS_PER_PAGE)}
|
||||||
|
disabled={chartStartIndex + ITEMS_PER_PAGE >= sortedApps.length}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
{" "}
|
||||||
|
{ITEMS_PER_PAGE}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<Dialog open={isTableOpen} onOpenChange={setIsTableOpen}>
|
||||||
|
<DialogContent className="max-w-2xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Applications Count</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="max-h-[60vh] overflow-y-auto">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead>Application</TableHead>
|
||||||
|
<TableHead className="text-right">Count</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{sortedApps.slice(0, tableLimit).map(([name, count]) => (
|
||||||
|
<TableRow key={name}>
|
||||||
|
<TableCell>{name}</TableCell>
|
||||||
|
<TableCell className="text-right">{count}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
{tableLimit < sortedApps.length && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-full"
|
||||||
|
onClick={() => setTableLimit(prev => prev + ITEMS_PER_PAGE)}
|
||||||
|
>
|
||||||
|
Load More
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import { ClipboardIcon, ExternalLink } from "lucide-react";
|
|
||||||
import { Fragment } from "react";
|
|
||||||
|
|
||||||
import handleCopy from "./handle-copy";
|
|
||||||
|
|
||||||
const URL_PATTERN = /(https?:\/\/[^\s,]+)/;
|
|
||||||
const CODE_PATTERN = /`([^`]*)`/;
|
|
||||||
|
|
||||||
export default function TextParseLinks(text: string) {
|
|
||||||
const codeParts = text.split(CODE_PATTERN);
|
|
||||||
|
|
||||||
return codeParts.map((part: string, codeIndex: number) => {
|
|
||||||
if (codeIndex % 2 === 1) {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
key={`code-${codeIndex}`}
|
|
||||||
className="bg-secondary py-1 px-2 rounded-lg inline-flex items-center gap-2"
|
|
||||||
>
|
|
||||||
{part}
|
|
||||||
<ClipboardIcon
|
|
||||||
className="size-3 cursor-pointer"
|
|
||||||
onClick={() => handleCopy("command", part)}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const urlParts = part.split(URL_PATTERN);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment key={`text-${codeIndex}`}>
|
|
||||||
{urlParts.map((urlPart: string, urlIndex: number) => {
|
|
||||||
if (urlIndex % 2 === 1) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
key={`url-${codeIndex}-${urlIndex}`}
|
|
||||||
href={urlPart}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="inline-flex items-center gap-1 text-blue-600 dark:text-blue-400 hover:underline font-medium transition-colors"
|
|
||||||
>
|
|
||||||
{urlPart}
|
|
||||||
<ExternalLink className="size-3" />
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <Fragment key={`plain-${codeIndex}-${urlIndex}`}>{urlPart}</Fragment>;
|
|
||||||
})}
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,369 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as RechartsPrimitive from "recharts"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
// Format: { THEME_NAME: CSS_SELECTOR }
|
|
||||||
const THEMES = { light: "", dark: ".dark" } as const
|
|
||||||
|
|
||||||
export type ChartConfig = {
|
|
||||||
[k in string]: {
|
|
||||||
label?: React.ReactNode
|
|
||||||
icon?: React.ComponentType
|
|
||||||
} & (
|
|
||||||
| { color?: string; theme?: never }
|
|
||||||
| { color?: never; theme: Record<keyof typeof THEMES, string> }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChartContextProps = {
|
|
||||||
config: ChartConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChartContext = React.createContext<ChartContextProps | null>(null)
|
|
||||||
|
|
||||||
function useChart() {
|
|
||||||
const context = React.useContext(ChartContext)
|
|
||||||
|
|
||||||
if (!context) {
|
|
||||||
throw new Error("useChart must be used within a <ChartContainer />")
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChartContainer = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<"div"> & {
|
|
||||||
config: ChartConfig
|
|
||||||
children: React.ComponentProps<
|
|
||||||
typeof RechartsPrimitive.ResponsiveContainer
|
|
||||||
>["children"]
|
|
||||||
}
|
|
||||||
>(({ id, className, children, config, ...props }, ref) => {
|
|
||||||
const uniqueId = React.useId()
|
|
||||||
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChartContext.Provider value={{ config }}>
|
|
||||||
<div
|
|
||||||
data-chart={chartId}
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ChartStyle id={chartId} config={config} />
|
|
||||||
<RechartsPrimitive.ResponsiveContainer>
|
|
||||||
{children}
|
|
||||||
</RechartsPrimitive.ResponsiveContainer>
|
|
||||||
</div>
|
|
||||||
</ChartContext.Provider>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ChartContainer.displayName = "Chart"
|
|
||||||
|
|
||||||
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
|
|
||||||
const colorConfig = Object.entries(config).filter(
|
|
||||||
([, config]) => config.theme || config.color
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!colorConfig.length) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<style
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: Object.entries(THEMES)
|
|
||||||
.map(
|
|
||||||
([theme, prefix]) => `
|
|
||||||
${prefix} [data-chart=${id}] {
|
|
||||||
${colorConfig
|
|
||||||
.map(([key, itemConfig]) => {
|
|
||||||
const color =
|
|
||||||
itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
|
|
||||||
itemConfig.color
|
|
||||||
return color ? ` --color-${key}: ${color};` : null
|
|
||||||
})
|
|
||||||
.join("\n")}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
)
|
|
||||||
.join("\n"),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChartTooltip = RechartsPrimitive.Tooltip
|
|
||||||
|
|
||||||
const ChartTooltipContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
|
||||||
React.ComponentProps<"div"> & {
|
|
||||||
hideLabel?: boolean
|
|
||||||
hideIndicator?: boolean
|
|
||||||
indicator?: "line" | "dot" | "dashed"
|
|
||||||
nameKey?: string
|
|
||||||
labelKey?: string
|
|
||||||
}
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
active,
|
|
||||||
payload,
|
|
||||||
className,
|
|
||||||
indicator = "dot",
|
|
||||||
hideLabel = false,
|
|
||||||
hideIndicator = false,
|
|
||||||
label,
|
|
||||||
labelFormatter,
|
|
||||||
labelClassName,
|
|
||||||
formatter,
|
|
||||||
color,
|
|
||||||
nameKey,
|
|
||||||
labelKey,
|
|
||||||
},
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const { config } = useChart()
|
|
||||||
|
|
||||||
const tooltipLabel = React.useMemo(() => {
|
|
||||||
if (hideLabel || !payload?.length) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const [item] = payload
|
|
||||||
const key = `${labelKey || item?.dataKey || item?.name || "value"}`
|
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
||||||
const value =
|
|
||||||
!labelKey && typeof label === "string"
|
|
||||||
? config[label as keyof typeof config]?.label || label
|
|
||||||
: itemConfig?.label
|
|
||||||
|
|
||||||
if (labelFormatter) {
|
|
||||||
return (
|
|
||||||
<div className={cn("font-medium", labelClassName)}>
|
|
||||||
{labelFormatter(value, payload)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className={cn("font-medium", labelClassName)}>{value}</div>
|
|
||||||
}, [
|
|
||||||
label,
|
|
||||||
labelFormatter,
|
|
||||||
payload,
|
|
||||||
hideLabel,
|
|
||||||
labelClassName,
|
|
||||||
config,
|
|
||||||
labelKey,
|
|
||||||
])
|
|
||||||
|
|
||||||
if (!active || !payload?.length) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const nestLabel = payload.length === 1 && indicator !== "dot"
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{!nestLabel ? tooltipLabel : null}
|
|
||||||
<div className="grid gap-1.5">
|
|
||||||
{payload
|
|
||||||
.filter((item) => item.type !== "none")
|
|
||||||
.map((item, index) => {
|
|
||||||
const key = `${nameKey || item.name || item.dataKey || "value"}`
|
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
||||||
const indicatorColor = color || item.payload.fill || item.color
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={item.dataKey}
|
|
||||||
className={cn(
|
|
||||||
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
|
|
||||||
indicator === "dot" && "items-center"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{formatter && item?.value !== undefined && item.name ? (
|
|
||||||
formatter(item.value, item.name, item, index, item.payload)
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{itemConfig?.icon ? (
|
|
||||||
<itemConfig.icon />
|
|
||||||
) : (
|
|
||||||
!hideIndicator && (
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
|
|
||||||
{
|
|
||||||
"h-2.5 w-2.5": indicator === "dot",
|
|
||||||
"w-1": indicator === "line",
|
|
||||||
"w-0 border-[1.5px] border-dashed bg-transparent":
|
|
||||||
indicator === "dashed",
|
|
||||||
"my-0.5": nestLabel && indicator === "dashed",
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--color-bg": indicatorColor,
|
|
||||||
"--color-border": indicatorColor,
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"flex flex-1 justify-between leading-none",
|
|
||||||
nestLabel ? "items-end" : "items-center"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="grid gap-1.5">
|
|
||||||
{nestLabel ? tooltipLabel : null}
|
|
||||||
<span className="text-muted-foreground">
|
|
||||||
{itemConfig?.label || item.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{item.value && (
|
|
||||||
<span className="font-mono font-medium tabular-nums text-foreground">
|
|
||||||
{item.value.toLocaleString()}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ChartTooltipContent.displayName = "ChartTooltip"
|
|
||||||
|
|
||||||
const ChartLegend = RechartsPrimitive.Legend
|
|
||||||
|
|
||||||
const ChartLegendContent = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<"div"> &
|
|
||||||
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
|
||||||
hideIcon?: boolean
|
|
||||||
nameKey?: string
|
|
||||||
}
|
|
||||||
>(
|
|
||||||
(
|
|
||||||
{ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const { config } = useChart()
|
|
||||||
|
|
||||||
if (!payload?.length) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex items-center justify-center gap-4",
|
|
||||||
verticalAlign === "top" ? "pb-3" : "pt-3",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{payload
|
|
||||||
.filter((item) => item.type !== "none")
|
|
||||||
.map((item) => {
|
|
||||||
const key = `${nameKey || item.dataKey || "value"}`
|
|
||||||
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={item.value}
|
|
||||||
className={cn(
|
|
||||||
"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{itemConfig?.icon && !hideIcon ? (
|
|
||||||
<itemConfig.icon />
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className="h-2 w-2 shrink-0 rounded-[2px]"
|
|
||||||
style={{
|
|
||||||
backgroundColor: item.color,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{itemConfig?.label}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ChartLegendContent.displayName = "ChartLegend"
|
|
||||||
|
|
||||||
// Helper to extract item config from a payload.
|
|
||||||
function getPayloadConfigFromPayload(
|
|
||||||
config: ChartConfig,
|
|
||||||
payload: unknown,
|
|
||||||
key: string
|
|
||||||
) {
|
|
||||||
if (typeof payload !== "object" || payload === null) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const payloadPayload =
|
|
||||||
"payload" in payload &&
|
|
||||||
typeof payload.payload === "object" &&
|
|
||||||
payload.payload !== null
|
|
||||||
? payload.payload
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
let configLabelKey: string = key
|
|
||||||
|
|
||||||
if (
|
|
||||||
key in payload &&
|
|
||||||
typeof payload[key as keyof typeof payload] === "string"
|
|
||||||
) {
|
|
||||||
configLabelKey = payload[key as keyof typeof payload] as string
|
|
||||||
} else if (
|
|
||||||
payloadPayload &&
|
|
||||||
key in payloadPayload &&
|
|
||||||
typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
|
|
||||||
) {
|
|
||||||
configLabelKey = payloadPayload[
|
|
||||||
key as keyof typeof payloadPayload
|
|
||||||
] as string
|
|
||||||
}
|
|
||||||
|
|
||||||
return configLabelKey in config
|
|
||||||
? config[configLabelKey]
|
|
||||||
: config[key as keyof typeof config]
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
ChartContainer,
|
|
||||||
ChartTooltip,
|
|
||||||
ChartTooltipContent,
|
|
||||||
ChartLegend,
|
|
||||||
ChartLegendContent,
|
|
||||||
ChartStyle,
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useInView, useMotionValue, useSpring } from "motion/react";
|
import { useInView, useMotionValue, useSpring } from "framer-motion";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const ScrollArea = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<ScrollAreaPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn("relative overflow-hidden", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
|
||||||
{children}
|
|
||||||
</ScrollAreaPrimitive.Viewport>
|
|
||||||
<ScrollBar />
|
|
||||||
<ScrollAreaPrimitive.Corner />
|
|
||||||
</ScrollAreaPrimitive.Root>
|
|
||||||
))
|
|
||||||
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
|
||||||
|
|
||||||
const ScrollBar = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
||||||
>(({ className, orientation = "vertical", ...props }, ref) => (
|
|
||||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
||||||
ref={ref}
|
|
||||||
orientation={orientation}
|
|
||||||
className={cn(
|
|
||||||
"flex touch-none select-none transition-colors",
|
|
||||||
orientation === "vertical" &&
|
|
||||||
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
|
||||||
orientation === "horizontal" &&
|
|
||||||
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
|
||||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
||||||
))
|
|
||||||
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
|
||||||
|
|
||||||
export { ScrollArea, ScrollBar }
|
|
||||||
@@ -5,7 +5,7 @@ import React from "react";
|
|||||||
import type { OperatingSystem } from "@/lib/types";
|
import type { OperatingSystem } from "@/lib/types";
|
||||||
|
|
||||||
// eslint-disable-next-line node/no-process-env
|
// eslint-disable-next-line node/no-process-env
|
||||||
export const basePath = process.env.BASE_PATH || "ProxmoxVE";
|
export const basePath = process.env.BASE_PATH || "";
|
||||||
|
|
||||||
export const navbarLinks = [
|
export const navbarLinks = [
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user