mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-11-04 18:32:51 +00:00
Compare commits
68 Commits
2025-09-01
...
2025-09-07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
751f488f9e | ||
|
|
0ed4363247 | ||
|
|
e77612c27e | ||
|
|
59c8e214af | ||
|
|
c790f03a6b | ||
|
|
54d4d58b15 | ||
|
|
889a58c00e | ||
|
|
e9a5d7587a | ||
|
|
6f84046741 | ||
|
|
ff96351db8 | ||
|
|
1b632199b3 | ||
|
|
9fb02a93b4 | ||
|
|
3aa56651d8 | ||
|
|
17d4c59041 | ||
|
|
2bfb35779b | ||
|
|
83b93390c9 | ||
|
|
7ce47ad414 | ||
|
|
646e0c31f4 | ||
|
|
0c7e200a94 | ||
|
|
a9b02b3e9c | ||
|
|
b62adc2c5c | ||
|
|
3438b046e5 | ||
|
|
cbd6d6d0f3 | ||
|
|
cf6c429c57 | ||
|
|
bbe71cbbb9 | ||
|
|
9b6a736c8c | ||
|
|
c395ccc270 | ||
|
|
3dd72e08e9 | ||
|
|
1d989bea73 | ||
|
|
f881b88344 | ||
|
|
06dbad83ef | ||
|
|
7ff966b042 | ||
|
|
62264f37a6 | ||
|
|
bf05dabc4c | ||
|
|
bc229d9738 | ||
|
|
969b08caa8 | ||
|
|
c1c43ed2cb | ||
|
|
e74767d1a4 | ||
|
|
e9e17f4f51 | ||
|
|
2c1b15a40e | ||
|
|
a4bfaf1646 | ||
|
|
6fa12cc814 | ||
|
|
d314168a37 | ||
|
|
d6ad11c5c2 | ||
|
|
534592b44a | ||
|
|
d9b6b58b36 | ||
|
|
298eb7e83d | ||
|
|
c2dd1e413f | ||
|
|
a4f1766408 | ||
|
|
a24169e9b8 | ||
|
|
45a2163e66 | ||
|
|
2fc3e62d60 | ||
|
|
210b846d61 | ||
|
|
b04cfb65f7 | ||
|
|
6a2fc4083b | ||
|
|
f7f53943c2 | ||
|
|
31f4d9b16c | ||
|
|
cd4cd5eec1 | ||
|
|
8a7eeee727 | ||
|
|
be5d65f421 | ||
|
|
591af3f109 | ||
|
|
a3e0df9de1 | ||
|
|
596699d07e | ||
|
|
b2275b44c2 | ||
|
|
737842fb1e | ||
|
|
646cb2bc30 | ||
|
|
4599bfe052 | ||
|
|
bb85b1d4ac |
98
CHANGELOG.md
98
CHANGELOG.md
@@ -10,8 +10,106 @@
|
|||||||
> [!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-09-08
|
||||||
|
|
||||||
|
## 2025-09-07
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Update ExecStart path for karakeep service [@CrazyWolf13](https://github.com/CrazyWolf13) ([#7460](https://github.com/community-scripts/ProxmoxVE/pull/7460))
|
||||||
|
|
||||||
|
## 2025-09-06
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- Resilio Sync ([#7442](https://github.com/community-scripts/ProxmoxVE/pull/7442))
|
||||||
|
- leantime ([#7414](https://github.com/community-scripts/ProxmoxVE/pull/7414))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- use debian source for direct installation of MQTT [@EtlamGit](https://github.com/EtlamGit) ([#7423](https://github.com/community-scripts/ProxmoxVE/pull/7423))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- feat: added mobile ui subscription nag removal [@ivan-penchev](https://github.com/ivan-penchev) ([#7164](https://github.com/community-scripts/ProxmoxVE/pull/7164))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- #### 📝 Script Information
|
||||||
|
|
||||||
|
- MediaManager Configuration Path [@austinpilz](https://github.com/austinpilz) ([#7408](https://github.com/community-scripts/ProxmoxVE/pull/7408))
|
||||||
|
- Paperless-NGX: Remove default credentials from json [@tremor021](https://github.com/tremor021) ([#7403](https://github.com/community-scripts/ProxmoxVE/pull/7403))
|
||||||
|
|
||||||
|
## 2025-09-05
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- Tududi: Pin version to 0.80 [@vhsdream](https://github.com/vhsdream) ([#7420](https://github.com/community-scripts/ProxmoxVE/pull/7420))
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- AdventureLog: Update dependencies [@tremor021](https://github.com/tremor021) ([#7404](https://github.com/community-scripts/ProxmoxVE/pull/7404))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- refactor: Enhance ScriptAccordion and Sidebar components to support selectedCategory state [@BramSuurdje](https://github.com/BramSuurdje) ([#7405](https://github.com/community-scripts/ProxmoxVE/pull/7405))
|
||||||
|
|
||||||
|
## 2025-09-04
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- fix: Syntax error in Immich scripts [@henworth](https://github.com/henworth) ([#7398](https://github.com/community-scripts/ProxmoxVE/pull/7398))
|
||||||
|
- Netdata: Fix pve_check for 8 [@MickLesk](https://github.com/MickLesk) ([#7392](https://github.com/community-scripts/ProxmoxVE/pull/7392))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Immich: pin compiled photo library revisions [@vhsdream](https://github.com/vhsdream) ([#7395](https://github.com/community-scripts/ProxmoxVE/pull/7395))
|
||||||
|
|
||||||
|
## 2025-09-03
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Element-Synapse: Increase HDD size [@tremor021](https://github.com/tremor021) ([#7384](https://github.com/community-scripts/ProxmoxVE/pull/7384))
|
||||||
|
- Wizarr: fix uv lock issue; use correct output suppression [@vhsdream](https://github.com/vhsdream) ([#7378](https://github.com/community-scripts/ProxmoxVE/pull/7378))
|
||||||
|
- Netbox: Fix missing directory [@tremor021](https://github.com/tremor021) ([#7374](https://github.com/community-scripts/ProxmoxVE/pull/7374))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Enhanced IP-Tag installation script with interactive configuration, improved VM IP detection, and better visual indicators [@DesertGamer](https://github.com/DesertGamer) ([#7366](https://github.com/community-scripts/ProxmoxVE/pull/7366))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fix navigation [@BramSuurdje](https://github.com/BramSuurdje) ([#7376](https://github.com/community-scripts/ProxmoxVE/pull/7376))
|
||||||
|
|
||||||
## 2025-09-02
|
## 2025-09-02
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- Increase default disk size for Apt-Cacher-NG [@MickLesk](https://github.com/MickLesk) ([#7352](https://github.com/community-scripts/ProxmoxVE/pull/7352))
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Snipe-IT: Fix Nginx configuration [@tremor021](https://github.com/tremor021) ([#7358](https://github.com/community-scripts/ProxmoxVE/pull/7358))
|
||||||
|
- booklore: remove folder before update [@MickLesk](https://github.com/MickLesk) ([#7351](https://github.com/community-scripts/ProxmoxVE/pull/7351))
|
||||||
|
|
||||||
|
- #### ✨ New Features
|
||||||
|
|
||||||
|
- Immich: bump version to 1.140.1 [@vhsdream](https://github.com/vhsdream) ([#7349](https://github.com/community-scripts/ProxmoxVE/pull/7349))
|
||||||
|
|
||||||
|
### 🌐 Website
|
||||||
|
|
||||||
|
- #### 📝 Script Information
|
||||||
|
|
||||||
|
- pbs: increase note on website for ipv6 [@MickLesk](https://github.com/MickLesk) ([#7339](https://github.com/community-scripts/ProxmoxVE/pull/7339))
|
||||||
|
|
||||||
## 2025-09-01
|
## 2025-09-01
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
if ! command -v memcached >/dev/null 2>&1; then
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get install -y memcached libmemcached-tools
|
||||||
|
fi
|
||||||
if check_for_gh_release "adventurelog" "seanmorley15/adventurelog"; then
|
if check_for_gh_release "adventurelog" "seanmorley15/adventurelog"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop adventurelog-backend
|
systemctl stop adventurelog-backend
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ APP="Apt-Cacher-NG"
|
|||||||
var_tags="${var_tags:-caching}"
|
var_tags="${var_tags:-caching}"
|
||||||
var_cpu="${var_cpu:-1}"
|
var_cpu="${var_cpu:-1}"
|
||||||
var_ram="${var_ram:-512}"
|
var_ram="${var_ram:-512}"
|
||||||
var_disk="${var_disk:-2}"
|
var_disk="${var_disk:-10}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-12}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
@@ -20,18 +20,18 @@ 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 /var ]]; then
|
if [[ ! -d /var ]]; then
|
||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
|
||||||
fi
|
|
||||||
msg_info "Updating $APP LXC"
|
|
||||||
$STD apt-get update
|
|
||||||
$STD apt-get -y upgrade
|
|
||||||
msg_ok "Updated $APP LXC"
|
|
||||||
exit
|
exit
|
||||||
|
fi
|
||||||
|
msg_info "Updating $APP LXC"
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get -y upgrade
|
||||||
|
msg_ok "Updated $APP LXC"
|
||||||
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
@@ -41,4 +41,4 @@ description
|
|||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3142/acng-report.html${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3142/acng-report.html${CL}"
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ function update_script() {
|
|||||||
systemctl stop booklore
|
systemctl stop booklore
|
||||||
msg_ok "Stopped $APP"
|
msg_ok "Stopped $APP"
|
||||||
|
|
||||||
|
msg_info "backup old install"
|
||||||
|
mv /opt/booklore /opt/booklore_bak
|
||||||
|
msg_ok "backup done"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore"
|
fetch_and_deploy_gh_release "booklore" "booklore-app/BookLore"
|
||||||
|
|
||||||
msg_info "Building Frontend"
|
msg_info "Building Frontend"
|
||||||
@@ -58,6 +62,7 @@ function update_script() {
|
|||||||
msg_info "Starting $APP"
|
msg_info "Starting $APP"
|
||||||
systemctl start booklore
|
systemctl start booklore
|
||||||
systemctl reload nginx
|
systemctl reload nginx
|
||||||
|
rm -rf /opt/booklore_bak
|
||||||
msg_ok "Started $APP"
|
msg_ok "Started $APP"
|
||||||
msg_ok "Updated Successfully"
|
msg_ok "Updated Successfully"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ APP="Element Synapse"
|
|||||||
var_tags="${var_tags:-server}"
|
var_tags="${var_tags:-server}"
|
||||||
var_cpu="${var_cpu:-1}"
|
var_cpu="${var_cpu:-1}"
|
||||||
var_ram="${var_ram:-2048}"
|
var_ram="${var_ram:-2048}"
|
||||||
var_disk="${var_disk:-4}"
|
var_disk="${var_disk:-8}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-12}"
|
var_version="${var_version:-12}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|||||||
6
ct/headers/leantime
Normal file
6
ct/headers/leantime
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
__ __ _
|
||||||
|
/ / ___ ____ _____ / /_(_)___ ___ ___
|
||||||
|
/ / / _ \/ __ `/ __ \/ __/ / __ `__ \/ _ \
|
||||||
|
/ /___/ __/ /_/ / / / / /_/ / / / / / / __/
|
||||||
|
/_____/\___/\__,_/_/ /_/\__/_/_/ /_/ /_/\___/
|
||||||
|
|
||||||
6
ct/headers/resiliosync
Normal file
6
ct/headers/resiliosync
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
____ _ ___ _____
|
||||||
|
/ __ \___ _____(_) (_)___ / ___/__ ______ _____
|
||||||
|
/ /_/ / _ \/ ___/ / / / __ \ \__ \/ / / / __ \/ ___/
|
||||||
|
/ _, _/ __(__ ) / / / /_/ / ___/ / /_/ / / / / /__
|
||||||
|
/_/ |_|\___/____/_/_/_/\____/ /____/\__, /_/ /_/\___/
|
||||||
|
/____/
|
||||||
17
ct/immich.sh
17
ct/immich.sh
@@ -61,7 +61,7 @@ function update_script() {
|
|||||||
done
|
done
|
||||||
msg_ok "Image-processing libraries up to date"
|
msg_ok "Image-processing libraries up to date"
|
||||||
fi
|
fi
|
||||||
RELEASE="1.140.0"
|
RELEASE="1.140.1"
|
||||||
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
|
||||||
@@ -206,7 +206,8 @@ function compile_libjxl() {
|
|||||||
SOURCE=${SOURCE_DIR}/libjxl
|
SOURCE=${SOURCE_DIR}/libjxl
|
||||||
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
|
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
|
||||||
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
|
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
|
||||||
: "${LIBJXL_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libjxl.json)}"
|
# : "${LIBJXL_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libjxl.json)}"
|
||||||
|
: "${LIBJXL_REVISION:=794a5dcf0d54f9f0b20d288a12e87afb91d20dfc}"
|
||||||
if [[ "${update:-}" ]] || [[ "$LIBJXL_REVISION" != "$(grep 'libjxl' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
if [[ "${update:-}" ]] || [[ "$LIBJXL_REVISION" != "$(grep 'libjxl' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
||||||
msg_info "Recompiling libjxl"
|
msg_info "Recompiling libjxl"
|
||||||
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
||||||
@@ -253,7 +254,8 @@ function compile_libheif() {
|
|||||||
$STD apt-get install -y libaom-dev
|
$STD apt-get install -y libaom-dev
|
||||||
local update="required"
|
local update="required"
|
||||||
fi
|
fi
|
||||||
: "${LIBHEIF_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libheif.json)}"
|
# : "${LIBHEIF_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libheif.json)}"
|
||||||
|
: "${LIBHEIF_REVISION:=35dad50a9145332a7bfdf1ff6aef6801fb613d68}"
|
||||||
if [[ "${update:-}" ]] || [[ "$LIBHEIF_REVISION" != "$(grep 'libheif' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
if [[ "${update:-}" ]] || [[ "$LIBHEIF_REVISION" != "$(grep 'libheif' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
||||||
msg_info "Recompiling libheif"
|
msg_info "Recompiling libheif"
|
||||||
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
||||||
@@ -285,7 +287,8 @@ function compile_libheif() {
|
|||||||
function compile_libraw() {
|
function compile_libraw() {
|
||||||
SOURCE=${SOURCE_DIR}/libraw
|
SOURCE=${SOURCE_DIR}/libraw
|
||||||
local update
|
local update
|
||||||
: "${LIBRAW_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libraw.json)}"
|
# : "${LIBRAW_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libraw.json)}"
|
||||||
|
: "${LIBRAW_REVISION:=09bea31181b43e97959ee5452d91e5bc66365f1f}"
|
||||||
if [[ "${update:-}" ]] || [[ "$LIBRAW_REVISION" != "$(grep 'libraw' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
if [[ "${update:-}" ]] || [[ "$LIBRAW_REVISION" != "$(grep 'libraw' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
||||||
msg_info "Recompiling libraw"
|
msg_info "Recompiling libraw"
|
||||||
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
||||||
@@ -306,7 +309,8 @@ function compile_libraw() {
|
|||||||
|
|
||||||
function compile_imagemagick() {
|
function compile_imagemagick() {
|
||||||
SOURCE=$SOURCE_DIR/imagemagick
|
SOURCE=$SOURCE_DIR/imagemagick
|
||||||
: "${IMAGEMAGICK_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/imagemagick.json)}"
|
# : "${IMAGEMAGICK_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/imagemagick.json)}"
|
||||||
|
: "${IMAGEMAGICK_REVISION:=8289a3388a085ad5ae81aa6812f21554bdfd54f2}"
|
||||||
if [[ "${update:-}" ]] || [[ "$IMAGEMAGICK_REVISION" != "$(grep 'imagemagick' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
if [[ "${update:-}" ]] || [[ "$IMAGEMAGICK_REVISION" != "$(grep 'imagemagick' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
||||||
msg_info "Recompiling ImageMagick"
|
msg_info "Recompiling ImageMagick"
|
||||||
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
||||||
@@ -326,7 +330,8 @@ function compile_imagemagick() {
|
|||||||
|
|
||||||
function compile_libvips() {
|
function compile_libvips() {
|
||||||
SOURCE=$SOURCE_DIR/libvips
|
SOURCE=$SOURCE_DIR/libvips
|
||||||
: "${LIBVIPS_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libvips.json)}"
|
# : "${LIBVIPS_REVISION:=$(jq -cr '.revision' "$BASE_DIR"/server/sources/libvips.json)}"
|
||||||
|
: "${LIBVIPS_REVISION:=8fa37a64547e392d3808eed8d72adab7e02b3d00}"
|
||||||
if [[ "${update:-}" ]] || [[ "$LIBVIPS_REVISION" != "$(grep 'libvips' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
if [[ "${update:-}" ]] || [[ "$LIBVIPS_REVISION" != "$(grep 'libvips' ~/.immich_library_revisions | awk '{print $2}')" ]]; then
|
||||||
msg_info "Recompiling libvips"
|
msg_info "Recompiling libvips"
|
||||||
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
if [[ -d "$SOURCE" ]]; then rm -rf "$SOURCE"; fi
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ function update_script() {
|
|||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if grep -q '^ExecStart=/usr/bin/node\s\+dist/index\.mjs$' /etc/systemd/system/karakeep-workers.service; then
|
||||||
|
sed -i -E 's#^(ExecStart=/usr/bin/node\s+dist/)index\.mjs$#\1index.js#' /etc/systemd/system/karakeep-workers.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
fi
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "karakeep" "karakeep-app/karakeep"
|
fetch_and_deploy_gh_release "karakeep" "karakeep-app/karakeep"
|
||||||
if command -v corepack >/dev/null; then
|
if command -v corepack >/dev/null; then
|
||||||
$STD corepack disable
|
$STD corepack disable
|
||||||
|
|||||||
62
ct/leantime.sh
Normal file
62
ct/leantime.sh
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/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: Stroopwafe1
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://leantime.io
|
||||||
|
|
||||||
|
APP="Leantime"
|
||||||
|
var_tags="${var_tags:-productivity}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-20}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-12}"
|
||||||
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -d /opt/leantime ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if check_for_gh_release "leantime" "Leantime/leantime"; then
|
||||||
|
msg_info "Creating Backup"
|
||||||
|
mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql"
|
||||||
|
tar -czf "/opt/${APP}_backup_$(date +%F).tar.gz" "/opt/${APP}"
|
||||||
|
mv /opt/leantime /opt/leantime_bak
|
||||||
|
msg_ok "Backup Created"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "leantime" "Leantime/leantime" "prebuild" "latest" "/opt/leantime" Leantime*.tar.gz
|
||||||
|
|
||||||
|
msg_info "Restoring Config & Permissions"
|
||||||
|
mv /opt/leantime_bak/config/.env /opt/leantime/config/.env
|
||||||
|
chown -R www-data:www-data "/opt/leantime"
|
||||||
|
chmod -R 750 "/opt/leantime"
|
||||||
|
msg_ok "Restored Config & Permissions"
|
||||||
|
|
||||||
|
msg_info "Removing Backup"
|
||||||
|
rm -rf /opt/leantime_bak
|
||||||
|
msg_ok "Removed Backup"
|
||||||
|
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}/install${CL}"
|
||||||
44
ct/resiliosync.sh
Normal file
44
ct/resiliosync.sh
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: David Bennett (dbinit)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://www.resilio.com/sync
|
||||||
|
|
||||||
|
APP="Resilio Sync"
|
||||||
|
var_tags="${var_tags:-sync}"
|
||||||
|
var_cpu="${var_cpu:-2}"
|
||||||
|
var_ram="${var_ram:-2048}"
|
||||||
|
var_disk="${var_disk:-8}"
|
||||||
|
var_os="${var_os:-debian}"
|
||||||
|
var_version="${var_version:-12}"
|
||||||
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
|
header_info "$APP"
|
||||||
|
variables
|
||||||
|
color
|
||||||
|
catch_errors
|
||||||
|
|
||||||
|
function update_script() {
|
||||||
|
header_info
|
||||||
|
check_container_storage
|
||||||
|
check_container_resources
|
||||||
|
if [[ ! -d /var/lib/resilio-sync ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
msg_info "Updating ${APP} LXC"
|
||||||
|
$STD apt-get update
|
||||||
|
$STD apt-get -y upgrade
|
||||||
|
msg_ok "Updated Successfully"
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
start
|
||||||
|
build_container
|
||||||
|
description
|
||||||
|
|
||||||
|
msg_ok "Completed Successfully!\n"
|
||||||
|
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||||
|
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||||
|
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8888${CL}"
|
||||||
@@ -27,6 +27,9 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then
|
||||||
|
sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf
|
||||||
|
fi
|
||||||
|
|
||||||
if check_for_gh_release "snipe-it" "snipe/snipe-it"; then
|
if check_for_gh_release "snipe-it" "snipe/snipe-it"; then
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ function update_script() {
|
|||||||
rm -rf /opt/tududi/backend/dist
|
rm -rf /opt/tududi/backend/dist
|
||||||
msg_ok "Backup and removed Files"
|
msg_ok "Backup and removed Files"
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "tududi" "chrisvel/tududi"
|
fetch_and_deploy_gh_release "tududi" "chrisvel/tududi" "tarball" "v0.80" "/opt/tududi"
|
||||||
|
|
||||||
msg_info "Updating ${APP}"
|
msg_info "Updating ${APP}"
|
||||||
cd /opt/tududi
|
cd /opt/tududi
|
||||||
|
|||||||
@@ -45,13 +45,14 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Updating $APP"
|
msg_info "Updating $APP"
|
||||||
cd /opt/wizarr
|
cd /opt/wizarr
|
||||||
/usr/local/bin/uv -q sync --locked
|
$STD /usr/local/bin/uv lock
|
||||||
$STD /usr/local/bin/uv -q run pybabel compile -d app/translations
|
$STD /usr/local/bin/uv sync --locked
|
||||||
|
$STD /usr/local/bin/uv run pybabel compile -d app/translations
|
||||||
$STD npm --prefix app/static install
|
$STD npm --prefix app/static install
|
||||||
$STD npm --prefix app/static run build:css
|
$STD npm --prefix app/static run build:css
|
||||||
mkdir -p ./.cache
|
mkdir -p ./.cache
|
||||||
$STD tar -xf "$BACKUP_FILE" --directory=/
|
$STD tar -xf "$BACKUP_FILE" --directory=/
|
||||||
$STD /usr/local/bin/uv -q run flask db upgrade
|
$STD /usr/local/bin/uv run flask db upgrade
|
||||||
msg_ok "Updated $APP"
|
msg_ok "Updated $APP"
|
||||||
|
|
||||||
msg_info "Starting $APP"
|
msg_info "Starting $APP"
|
||||||
@@ -61,7 +62,7 @@ function update_script() {
|
|||||||
msg_info "Cleaning Up"
|
msg_info "Cleaning Up"
|
||||||
rm -rf "$BACKUP_FILE"
|
rm -rf "$BACKUP_FILE"
|
||||||
msg_ok "Cleanup Completed"
|
msg_ok "Cleanup Completed"
|
||||||
msg_ok "Update Successfully"
|
msg_ok "Updated Successfully"
|
||||||
fi
|
fi
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ const nextConfig = {
|
|||||||
BASE_PATH: "ProxmoxVE",
|
BASE_PATH: "ProxmoxVE",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: true,
|
||||||
|
},
|
||||||
|
|
||||||
output: "export",
|
output: "export",
|
||||||
basePath: `/ProxmoxVE`,
|
basePath: `/ProxmoxVE`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 1,
|
"cpu": 1,
|
||||||
"ram": 512,
|
"ram": 512,
|
||||||
"hdd": 2,
|
"hdd": 10,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "12"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 1,
|
"cpu": 1,
|
||||||
"ram": 2048,
|
"ram": 2048,
|
||||||
"hdd": 4,
|
"hdd": 8,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "12"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
"password": null
|
"password": null
|
||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Please be aware that Immich releases are pinned to specific versions until compatibility has been confirmed by the Community Scripts maintainers; as a result, the version installed by the helper script may not be the most current version of Immich",
|
||||||
|
"type": "info"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"text": "During installation, you will be prompted with the option to install Intel OpenVINO for hardware-accelerated machine-learning. If you opt in, increase your LXC RAM after installation, as OpenVINO is memory-intensive",
|
"text": "During installation, you will be prompted with the option to install Intel OpenVINO for hardware-accelerated machine-learning. If you opt in, increase your LXC RAM after installation, as OpenVINO is memory-intensive",
|
||||||
"type": "info"
|
"type": "info"
|
||||||
|
|||||||
35
frontend/public/json/leantime.json
Normal file
35
frontend/public/json/leantime.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Leantime",
|
||||||
|
"slug": "leantime",
|
||||||
|
"categories": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"date_created": "2025-09-06",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 80,
|
||||||
|
"documentation": "https://docs.leantime.io/",
|
||||||
|
"config_path": "/opt/Leantime/config/.env",
|
||||||
|
"website": "https://leantime.io",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/leantime.webp",
|
||||||
|
"description": "Leantime is a goals focused project management system for non-project managers. Building with ADHD, Autism, and dyslexia in mind. ",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/leantime.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 2048,
|
||||||
|
"hdd": 20,
|
||||||
|
"os": "Debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 8000,
|
"interface_port": 8000,
|
||||||
"documentation": "https://maxdorninger.github.io/MediaManager/introduction.html",
|
"documentation": "https://maxdorninger.github.io/MediaManager/introduction.html",
|
||||||
"config_path": "/opt/mm_data/config.toml",
|
"config_path": "/opt/mm/config/config.toml",
|
||||||
"website": "https://github.com/maxdorninger/MediaManager",
|
"website": "https://github.com/maxdorninger/MediaManager",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mediamanager.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mediamanager.webp",
|
||||||
"description": "A modern selfhosted media management system for your media library",
|
"description": "A modern selfhosted media management system for your media library",
|
||||||
|
|||||||
@@ -1,44 +1,44 @@
|
|||||||
{
|
{
|
||||||
"name": "Paperless-ngx",
|
"name": "Paperless-ngx",
|
||||||
"slug": "paperless-ngx",
|
"slug": "paperless-ngx",
|
||||||
"categories": [
|
"categories": [
|
||||||
12
|
12
|
||||||
],
|
],
|
||||||
"date_created": "2024-05-02",
|
"date_created": "2024-05-02",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 8000,
|
"interface_port": 8000,
|
||||||
"documentation": "https://docs.paperless-ngx.com/",
|
"documentation": "https://docs.paperless-ngx.com/",
|
||||||
"website": "https://docs.paperless-ngx.com/",
|
"website": "https://docs.paperless-ngx.com/",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp",
|
||||||
"config_path": "/opt/paperless/paperless.conf",
|
"config_path": "/opt/paperless/paperless.conf",
|
||||||
"description": "Paperless-ngx is a software tool designed for digitizing and organizing paper documents. It provides a web-based interface for scanning, uploading, and organizing paper documents, making it easier to manage, search, and access important information. Paperless-ngx uses the OCR (Optical Character Recognition) technology to extract text from scanned images and makes it searchable, thus increasing the efficiency of document management.",
|
"description": "Paperless-ngx is a software tool designed for digitizing and organizing paper documents. It provides a web-based interface for scanning, uploading, and organizing paper documents, making it easier to manage, search, and access important information. Paperless-ngx uses the OCR (Optical Character Recognition) technology to extract text from scanned images and makes it searchable, thus increasing the efficiency of document management.",
|
||||||
"install_methods": [
|
"install_methods": [
|
||||||
{
|
{
|
||||||
"type": "default",
|
"type": "default",
|
||||||
"script": "ct/paperless-ngx.sh",
|
"script": "ct/paperless-ngx.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 2,
|
"cpu": 2,
|
||||||
"ram": 2048,
|
"ram": 2048,
|
||||||
"hdd": 12,
|
"hdd": 12,
|
||||||
"os": "debian",
|
"os": "debian",
|
||||||
"version": "12"
|
"version": "12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default_credentials": {
|
"default_credentials": {
|
||||||
"username": "admin",
|
"username": null,
|
||||||
"password": null
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "Show Login Credentials, type `cat ~/paperless-ngx.creds` in the LXC console",
|
||||||
|
"type": "info"
|
||||||
},
|
},
|
||||||
"notes": [
|
{
|
||||||
{
|
"text": "Script installs English as default OCR language. To install additional languages, use `apt-get install tesseract-ocr-[lang]`, where [lang] is the language code (e.g. `apt-get install tesseract-ocr-deu`).",
|
||||||
"text": "Show Login Credentials, type `cat ~/paperless-ngx.creds` in the LXC console",
|
"type": "info"
|
||||||
"type": "info"
|
}
|
||||||
},
|
]
|
||||||
{
|
|
||||||
"text": "Script installs English as default OCR language. To install additional languages, use `apt-get install tesseract-ocr-[lang]`, where [lang] is the language code (e.g. `apt-get install tesseract-ocr-deu`).",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"type": "warning"
|
"type": "warning"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "Advanced Install is only possible without root password and root SSH access, you can configure this after installation.",
|
"text": "Advanced Install is only possible with disabled IPV6! Otherwise the installation sometimes stuck.",
|
||||||
"type": "warning"
|
"type": "warning"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
40
frontend/public/json/resiliosync.json
Normal file
40
frontend/public/json/resiliosync.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "Resilio Sync",
|
||||||
|
"slug": "resiliosync",
|
||||||
|
"categories": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"date_created": "2025-09-06",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"config_path": "/etc/resilio-sync/config.json",
|
||||||
|
"interface_port": 8888,
|
||||||
|
"documentation": "https://help.resilio.com/",
|
||||||
|
"website": "https://www.resilio.com/sync",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/resilio-sync.webp",
|
||||||
|
"description": "Fast, reliable, and simple file sync and share solution, powered by P2P technology. Sync files across all your devices without storing them in the cloud.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/resilio-sync.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 2048,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"text": "After free registration, you will receive a license keyfile to your email address. Upload it into any LXC directory and select on first run.",
|
||||||
|
"type": "info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -73,7 +73,13 @@ function CategoryView() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleScriptClick = (scriptSlug: string) => {
|
const handleScriptClick = (scriptSlug: string) => {
|
||||||
router.push(`/scripts?id=${scriptSlug}`);
|
// Include category context when navigating to scripts
|
||||||
|
const categoryName = selectedCategoryIndex !== null ? categories[selectedCategoryIndex]?.name : null;
|
||||||
|
const queryParams = new URLSearchParams({ id: scriptSlug });
|
||||||
|
if (categoryName) {
|
||||||
|
queryParams.append("category", categoryName);
|
||||||
|
}
|
||||||
|
router.push(`/scripts?${queryParams.toString()}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateCategory = (direction: "prev" | "next") => {
|
const navigateCategory = (direction: "prev" | "next") => {
|
||||||
|
|||||||
@@ -4,12 +4,7 @@ import Link from "next/link";
|
|||||||
|
|
||||||
import type { Category } from "@/lib/types";
|
import type { Category } from "@/lib/types";
|
||||||
|
|
||||||
import {
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { formattedBadge } from "@/components/command-menu";
|
import { formattedBadge } from "@/components/command-menu";
|
||||||
import { basePath } from "@/config/site-config";
|
import { basePath } from "@/config/site-config";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@@ -18,14 +13,16 @@ export default function ScriptAccordion({
|
|||||||
items,
|
items,
|
||||||
selectedScript,
|
selectedScript,
|
||||||
setSelectedScript,
|
setSelectedScript,
|
||||||
|
selectedCategory,
|
||||||
|
setSelectedCategory,
|
||||||
}: {
|
}: {
|
||||||
items: Category[];
|
items: Category[];
|
||||||
selectedScript: string | null;
|
selectedScript: string | null;
|
||||||
setSelectedScript: (script: string | null) => void;
|
setSelectedScript: (script: string | null) => void;
|
||||||
|
selectedCategory: string | null;
|
||||||
|
setSelectedCategory: (category: string | null) => void;
|
||||||
}) {
|
}) {
|
||||||
const [expandedItem, setExpandedItem] = useState<string | undefined>(
|
const [expandedItem, setExpandedItem] = useState<string | undefined>(undefined);
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({});
|
const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({});
|
||||||
|
|
||||||
const handleAccordionChange = (value: string | undefined) => {
|
const handleAccordionChange = (value: string | undefined) => {
|
||||||
@@ -41,15 +38,27 @@ export default function ScriptAccordion({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedScript) {
|
if (selectedScript) {
|
||||||
const category = items.find(category =>
|
let category;
|
||||||
category.scripts.some(script => script.slug === selectedScript),
|
|
||||||
);
|
// If we have a selected category, try to find the script in that specific category
|
||||||
|
if (selectedCategory) {
|
||||||
|
category = items.find(
|
||||||
|
cat => cat.name === selectedCategory && cat.scripts.some(script => script.slug === selectedScript),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: if no category is selected or script not found in selected category,
|
||||||
|
// use the first category containing the script (backward compatibility)
|
||||||
|
if (!category) {
|
||||||
|
category = items.find(category => category.scripts.some(script => script.slug === selectedScript));
|
||||||
|
}
|
||||||
|
|
||||||
if (category) {
|
if (category) {
|
||||||
setExpandedItem(category.name);
|
setExpandedItem(category.name);
|
||||||
handleSelected(selectedScript);
|
handleSelected(selectedScript);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedScript, items, handleSelected]);
|
}, [selectedScript, selectedCategory, items, handleSelected]);
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
type="single"
|
type="single"
|
||||||
@@ -82,10 +91,7 @@ export default function ScriptAccordion({
|
|||||||
</div>
|
</div>
|
||||||
{" "}
|
{" "}
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent
|
<AccordionContent data-state={expandedItem === category.name ? "open" : "closed"} className="pt-0">
|
||||||
data-state={expandedItem === category.name ? "open" : "closed"}
|
|
||||||
className="pt-0"
|
|
||||||
>
|
|
||||||
{category.scripts
|
{category.scripts
|
||||||
.slice()
|
.slice()
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
@@ -94,7 +100,7 @@ export default function ScriptAccordion({
|
|||||||
<Link
|
<Link
|
||||||
href={{
|
href={{
|
||||||
pathname: "/scripts",
|
pathname: "/scripts",
|
||||||
query: { id: script.slug },
|
query: { id: script.slug, category: category.name },
|
||||||
}}
|
}}
|
||||||
prefetch={false}
|
prefetch={false}
|
||||||
className={`flex cursor-pointer items-center justify-between gap-1 px-1 py-1 text-muted-foreground hover:rounded-lg hover:bg-accent/60 hover:dark:bg-accent/20 ${
|
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 ${
|
||||||
@@ -102,7 +108,10 @@ export default function ScriptAccordion({
|
|||||||
? "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"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => handleSelected(script.slug)}
|
onClick={() => {
|
||||||
|
handleSelected(script.slug);
|
||||||
|
setSelectedCategory(category.name);
|
||||||
|
}}
|
||||||
ref={(el) => {
|
ref={(el) => {
|
||||||
linkRefs.current[script.slug] = el;
|
linkRefs.current[script.slug] = el;
|
||||||
}}
|
}}
|
||||||
@@ -113,15 +122,11 @@ export default function ScriptAccordion({
|
|||||||
height={16}
|
height={16}
|
||||||
width={16}
|
width={16}
|
||||||
unoptimized
|
unoptimized
|
||||||
onError={e =>
|
onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)}
|
||||||
((e.currentTarget as HTMLImageElement).src
|
|
||||||
= `/${basePath}/logo.png`)}
|
|
||||||
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>
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ function Sidebar({
|
|||||||
items,
|
items,
|
||||||
selectedScript,
|
selectedScript,
|
||||||
setSelectedScript,
|
setSelectedScript,
|
||||||
|
selectedCategory,
|
||||||
|
setSelectedCategory,
|
||||||
}: {
|
}: {
|
||||||
items: Category[];
|
items: Category[];
|
||||||
selectedScript: string | null;
|
selectedScript: string | null;
|
||||||
setSelectedScript: (script: string | null) => void;
|
setSelectedScript: (script: string | null) => void;
|
||||||
|
selectedCategory: string | null;
|
||||||
|
setSelectedCategory: (category: string | null) => void;
|
||||||
}) {
|
}) {
|
||||||
const uniqueScripts = items.reduce((acc, category) => {
|
const uniqueScripts = items.reduce((acc, category) => {
|
||||||
for (const script of category.scripts) {
|
for (const script of category.scripts) {
|
||||||
@@ -37,6 +41,8 @@ function Sidebar({
|
|||||||
items={items}
|
items={items}
|
||||||
selectedScript={selectedScript}
|
selectedScript={selectedScript}
|
||||||
setSelectedScript={setSelectedScript}
|
setSelectedScript={setSelectedScript}
|
||||||
|
selectedCategory={selectedCategory}
|
||||||
|
setSelectedCategory={setSelectedCategory}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,16 +8,14 @@ import type { Category, Script } from "@/lib/types";
|
|||||||
import { ScriptItem } from "@/app/scripts/_components/script-item";
|
import { ScriptItem } from "@/app/scripts/_components/script-item";
|
||||||
import { fetchCategories } from "@/lib/data";
|
import { fetchCategories } from "@/lib/data";
|
||||||
|
|
||||||
import {
|
import { LatestScripts, MostViewedScripts } from "./_components/script-info-blocks";
|
||||||
LatestScripts,
|
|
||||||
MostViewedScripts,
|
|
||||||
} from "./_components/script-info-blocks";
|
|
||||||
import Sidebar from "./_components/sidebar";
|
import Sidebar from "./_components/sidebar";
|
||||||
|
|
||||||
export const dynamic = "force-static";
|
export const dynamic = "force-static";
|
||||||
|
|
||||||
function ScriptContent() {
|
function ScriptContent() {
|
||||||
const [selectedScript, setSelectedScript] = useQueryState("id");
|
const [selectedScript, setSelectedScript] = useQueryState("id");
|
||||||
|
const [selectedCategory, setSelectedCategory] = useQueryState("category");
|
||||||
const [links, setLinks] = useState<Category[]>([]);
|
const [links, setLinks] = useState<Category[]>([]);
|
||||||
const [item, setItem] = useState<Script>();
|
const [item, setItem] = useState<Script>();
|
||||||
|
|
||||||
@@ -47,6 +45,8 @@ function ScriptContent() {
|
|||||||
items={links}
|
items={links}
|
||||||
selectedScript={selectedScript}
|
selectedScript={selectedScript}
|
||||||
setSelectedScript={setSelectedScript}
|
setSelectedScript={setSelectedScript}
|
||||||
|
selectedCategory={selectedCategory}
|
||||||
|
setSelectedCategory={setSelectedCategory}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx-4 w-full sm:mx-0 sm:ml-4">
|
<div className="mx-4 w-full sm:mx-0 sm:ml-4">
|
||||||
|
|||||||
@@ -36,19 +36,24 @@ export function formattedBadge(type: string) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// random Script
|
function getRandomScript(categories: Category[], previouslySelected: Set<string> = new Set()): Script | null {
|
||||||
function getRandomScript(categories: Category[]): Script | null {
|
|
||||||
const allScripts = categories.flatMap(cat => cat.scripts || []);
|
const allScripts = categories.flatMap(cat => cat.scripts || []);
|
||||||
if (allScripts.length === 0)
|
if (allScripts.length === 0)
|
||||||
return null;
|
return null;
|
||||||
const idx = Math.floor(Math.random() * allScripts.length);
|
|
||||||
return allScripts[idx];
|
const availableScripts = allScripts.filter(script => !previouslySelected.has(script.slug));
|
||||||
|
if (availableScripts.length === 0) {
|
||||||
|
return allScripts[Math.floor(Math.random() * allScripts.length)];
|
||||||
|
}
|
||||||
|
const idx = Math.floor(Math.random() * availableScripts.length);
|
||||||
|
return availableScripts[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CommandMenu() {
|
function CommandMenu() {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [links, setLinks] = React.useState<Category[]>([]);
|
const [links, setLinks] = React.useState<Category[]>([]);
|
||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
|
const [selectedScripts, setSelectedScripts] = React.useState<Set<string>>(new Set());
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const fetchSortedCategories = () => {
|
const fetchSortedCategories = () => {
|
||||||
@@ -65,25 +70,26 @@ export default function CommandMenu() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const down = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
fetchSortedCategories();
|
fetchSortedCategories();
|
||||||
setOpen(open => !open);
|
setOpen(open => !open);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
document.addEventListener("keydown", down);
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
return () => document.removeEventListener("keydown", down);
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const openRandomScript = async () => {
|
const handleOpenRandomScript = async () => {
|
||||||
if (links.length === 0) {
|
if (links.length === 0) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const categories = await fetchCategories();
|
const categories = await fetchCategories();
|
||||||
setLinks(categories);
|
setLinks(categories);
|
||||||
const randomScript = getRandomScript(categories);
|
const randomScript = getRandomScript(categories, selectedScripts);
|
||||||
if (randomScript) {
|
if (randomScript) {
|
||||||
|
setSelectedScripts(prev => new Set([...prev, randomScript.slug]));
|
||||||
router.push(`/scripts?id=${randomScript.slug}`);
|
router.push(`/scripts?id=${randomScript.slug}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,13 +98,54 @@ export default function CommandMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const randomScript = getRandomScript(links);
|
const randomScript = getRandomScript(links, selectedScripts);
|
||||||
if (randomScript) {
|
if (randomScript) {
|
||||||
|
setSelectedScripts(prev => new Set([...prev, randomScript.slug]));
|
||||||
router.push(`/scripts?id=${randomScript.slug}`);
|
router.push(`/scripts?id=${randomScript.slug}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getUniqueScriptsMap = React.useCallback(() => {
|
||||||
|
const scriptMap = new Map<string, { script: Script; categoryName: string }>();
|
||||||
|
for (const category of links) {
|
||||||
|
for (const script of category.scripts) {
|
||||||
|
if (!scriptMap.has(script.slug)) {
|
||||||
|
scriptMap.set(script.slug, { script, categoryName: category.name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scriptMap;
|
||||||
|
}, [links]);
|
||||||
|
|
||||||
|
const getUniqueScriptsByCategory = React.useCallback(() => {
|
||||||
|
const scriptMap = getUniqueScriptsMap();
|
||||||
|
const categoryOrder = links.map(cat => cat.name);
|
||||||
|
const grouped: Record<string, Script[]> = {};
|
||||||
|
|
||||||
|
for (const name of categoryOrder) {
|
||||||
|
grouped[name] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const { script, categoryName } of scriptMap.values()) {
|
||||||
|
if (grouped[categoryName]) {
|
||||||
|
grouped[categoryName].push(script);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grouped[categoryName] = [script];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(grouped).forEach((cat) => {
|
||||||
|
if (grouped[cat].length === 0)
|
||||||
|
delete grouped[cat];
|
||||||
|
});
|
||||||
|
|
||||||
|
return grouped;
|
||||||
|
}, [getUniqueScriptsMap, links]);
|
||||||
|
|
||||||
|
const uniqueScriptsByCategory = getUniqueScriptsByCategory();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
@@ -122,7 +169,20 @@ export default function CommandMenu() {
|
|||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip delayDuration={100}>
|
<Tooltip delayDuration={100}>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button variant="outline" size="icon" onClick={openRandomScript} disabled={isLoading} className="hidden lg:flex">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={handleOpenRandomScript}
|
||||||
|
disabled={isLoading}
|
||||||
|
className="hidden lg:flex"
|
||||||
|
aria-label="Open Random Script"
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
handleOpenRandomScript();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Sparkles className="size-4" />
|
<Sparkles className="size-4" />
|
||||||
<span className="sr-only">Open Random Script</span>
|
<span className="sr-only">Open Random Script</span>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -139,16 +199,24 @@ export default function CommandMenu() {
|
|||||||
<CommandInput placeholder="Search for a script..." />
|
<CommandInput placeholder="Search for a script..." />
|
||||||
<CommandList>
|
<CommandList>
|
||||||
<CommandEmpty>{isLoading ? "Loading..." : "No scripts found."}</CommandEmpty>
|
<CommandEmpty>{isLoading ? "Loading..." : "No scripts found."}</CommandEmpty>
|
||||||
{links.map(category => (
|
{Object.entries(uniqueScriptsByCategory).map(([categoryName, scripts]) => (
|
||||||
<CommandGroup key={`category:${category.name}`} heading={category.name}>
|
<CommandGroup key={`category:${categoryName}`} heading={categoryName}>
|
||||||
{category.scripts.map(script => (
|
{scripts.map(script => (
|
||||||
<CommandItem
|
<CommandItem
|
||||||
key={`script:${script.slug}`}
|
key={`script:${script.slug}`}
|
||||||
value={`${script.slug}-${script.name}`}
|
value={`${script.name}-${script.type}`}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
router.push(`/scripts?id=${script.slug}`);
|
router.push(`/scripts?id=${script.slug}`);
|
||||||
}}
|
}}
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label={`Open script ${script.name}`}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter" || e.key === " ") {
|
||||||
|
setOpen(false);
|
||||||
|
router.push(`/scripts?id=${script.slug}`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex gap-2" onClick={() => setOpen(false)}>
|
<div className="flex gap-2" onClick={() => setOpen(false)}>
|
||||||
<Image
|
<Image
|
||||||
@@ -172,3 +240,5 @@ export default function CommandMenu() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default CommandMenu;
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ msg_info "Installing Dependencies"
|
|||||||
$STD apt-get install -y \
|
$STD apt-get install -y \
|
||||||
gdal-bin \
|
gdal-bin \
|
||||||
libgdal-dev \
|
libgdal-dev \
|
||||||
git
|
git \
|
||||||
|
memcached \
|
||||||
|
libmemcached-tools
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
PYTHON_VERSION="3.12" setup_uv
|
PYTHON_VERSION="3.12" setup_uv
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ cd "$STAGING_DIR"
|
|||||||
SOURCE=${SOURCE_DIR}/libjxl
|
SOURCE=${SOURCE_DIR}/libjxl
|
||||||
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
|
JPEGLI_LIBJPEG_LIBRARY_SOVERSION="62"
|
||||||
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
|
JPEGLI_LIBJPEG_LIBRARY_VERSION="62.3.0"
|
||||||
: "${LIBJXL_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libjxl.json)}"
|
# : "${LIBJXL_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libjxl.json)}"
|
||||||
|
: "${LIBJXL_REVISION:=794a5dcf0d54f9f0b20d288a12e87afb91d20dfc}"
|
||||||
$STD git clone https://github.com/libjxl/libjxl.git "$SOURCE"
|
$STD git clone https://github.com/libjxl/libjxl.git "$SOURCE"
|
||||||
cd "$SOURCE"
|
cd "$SOURCE"
|
||||||
$STD git reset --hard "$LIBJXL_REVISION"
|
$STD git reset --hard "$LIBJXL_REVISION"
|
||||||
@@ -204,7 +205,8 @@ cd "$STAGING_DIR"
|
|||||||
rm -rf "$SOURCE"/{build,third_party}
|
rm -rf "$SOURCE"/{build,third_party}
|
||||||
|
|
||||||
SOURCE=${SOURCE_DIR}/libheif
|
SOURCE=${SOURCE_DIR}/libheif
|
||||||
: "${LIBHEIF_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libheif.json)}"
|
# : "${LIBHEIF_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libheif.json)}"
|
||||||
|
: "${LIBHEIF_REVISION:=35dad50a9145332a7bfdf1ff6aef6801fb613d68}"
|
||||||
$STD git clone https://github.com/strukturag/libheif.git "$SOURCE"
|
$STD git clone https://github.com/strukturag/libheif.git "$SOURCE"
|
||||||
cd "$SOURCE"
|
cd "$SOURCE"
|
||||||
$STD git reset --hard "$LIBHEIF_REVISION"
|
$STD git reset --hard "$LIBHEIF_REVISION"
|
||||||
@@ -227,7 +229,8 @@ cd "$STAGING_DIR"
|
|||||||
rm -rf "$SOURCE"/build
|
rm -rf "$SOURCE"/build
|
||||||
|
|
||||||
SOURCE=${SOURCE_DIR}/libraw
|
SOURCE=${SOURCE_DIR}/libraw
|
||||||
: "${LIBRAW_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libraw.json)}"
|
# : "${LIBRAW_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libraw.json)}"
|
||||||
|
: "${LIBRAW_REVISION:=09bea31181b43e97959ee5452d91e5bc66365f1f}"
|
||||||
$STD git clone https://github.com/libraw/libraw.git "$SOURCE"
|
$STD git clone https://github.com/libraw/libraw.git "$SOURCE"
|
||||||
cd "$SOURCE"
|
cd "$SOURCE"
|
||||||
$STD git reset --hard "$LIBRAW_REVISION"
|
$STD git reset --hard "$LIBRAW_REVISION"
|
||||||
@@ -240,7 +243,8 @@ $STD make clean
|
|||||||
cd "$STAGING_DIR"
|
cd "$STAGING_DIR"
|
||||||
|
|
||||||
SOURCE=$SOURCE_DIR/imagemagick
|
SOURCE=$SOURCE_DIR/imagemagick
|
||||||
: "${IMAGEMAGICK_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/imagemagick.json)}"
|
# : "${IMAGEMAGICK_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/imagemagick.json)}"
|
||||||
|
: "${IMAGEMAGICK_REVISION:=8289a3388a085ad5ae81aa6812f21554bdfd54f2}"
|
||||||
$STD git clone https://github.com/ImageMagick/ImageMagick.git "$SOURCE"
|
$STD git clone https://github.com/ImageMagick/ImageMagick.git "$SOURCE"
|
||||||
cd "$SOURCE"
|
cd "$SOURCE"
|
||||||
$STD git reset --hard "$IMAGEMAGICK_REVISION"
|
$STD git reset --hard "$IMAGEMAGICK_REVISION"
|
||||||
@@ -252,7 +256,8 @@ $STD make clean
|
|||||||
cd "$STAGING_DIR"
|
cd "$STAGING_DIR"
|
||||||
|
|
||||||
SOURCE=$SOURCE_DIR/libvips
|
SOURCE=$SOURCE_DIR/libvips
|
||||||
: "${LIBVIPS_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libvips.json)}"
|
# : "${LIBVIPS_REVISION:=$(jq -cr '.revision' $BASE_DIR/server/sources/libvips.json)}"
|
||||||
|
: "${LIBVIPS_REVISION:=8fa37a64547e392d3808eed8d72adab7e02b3d00}"
|
||||||
$STD git clone https://github.com/libvips/libvips.git "$SOURCE"
|
$STD git clone https://github.com/libvips/libvips.git "$SOURCE"
|
||||||
cd "$SOURCE"
|
cd "$SOURCE"
|
||||||
$STD git reset --hard "$LIBVIPS_REVISION"
|
$STD git reset --hard "$LIBVIPS_REVISION"
|
||||||
@@ -280,7 +285,7 @@ GEO_DIR="${INSTALL_DIR}/geodata"
|
|||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
|
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v1.140.0" "$SRC_DIR"
|
fetch_and_deploy_gh_release "immich" "immich-app/immich" "tarball" "v1.140.1" "$SRC_DIR"
|
||||||
|
|
||||||
msg_info "Installing ${APPLICATION} (more patience please)"
|
msg_info "Installing ${APPLICATION} (more patience please)"
|
||||||
|
|
||||||
|
|||||||
78
install/leantime-install.sh
Normal file
78
install/leantime-install.sh
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: Stroopwafe1
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://leantime.io
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" PHP_FPM="YES" setup_php
|
||||||
|
setup_mariadb
|
||||||
|
|
||||||
|
msg_info "Setting up Database"
|
||||||
|
DB_NAME=leantime
|
||||||
|
DB_USER=leantime
|
||||||
|
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
||||||
|
$STD mysql -u root -e "CREATE DATABASE $DB_NAME;"
|
||||||
|
$STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$DB_PASS');"
|
||||||
|
$STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
|
||||||
|
{
|
||||||
|
echo "Leantime Credentials"
|
||||||
|
echo "Database User: $DB_USER"
|
||||||
|
echo "Database Password: $DB_PASS"
|
||||||
|
echo "Database Name: $DB_NAME"
|
||||||
|
} >>~/leantime.creds
|
||||||
|
msg_ok "Set up Database"
|
||||||
|
|
||||||
|
fetch_and_deploy_gh_release "leantime" "Leantime/leantime" "prebuild" "latest" "/opt/leantime" Leantime*.tar.gz
|
||||||
|
|
||||||
|
msg_info "Setup Leantime"
|
||||||
|
chown -R www-data:www-data "/opt/leantime"
|
||||||
|
chmod -R 750 "/opt/leantime"
|
||||||
|
cat <<EOF >/etc/apache2/sites-enabled/000-default.conf
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerAdmin webmaster@localhost
|
||||||
|
DocumentRoot /opt/leantime/public
|
||||||
|
DirectoryIndex index.php index.html index.cgi index.pl index.xhtml
|
||||||
|
Options +ExecCGI
|
||||||
|
|
||||||
|
<Directory /opt/leantime/>
|
||||||
|
Options FollowSymLinks
|
||||||
|
Require all granted
|
||||||
|
AllowOverride All
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<Location />
|
||||||
|
Require all granted
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
ErrorLog /var/log/apache2/error.log
|
||||||
|
CustomLog /var/log/apache2/access.log combined
|
||||||
|
</VirtualHost>
|
||||||
|
EOF
|
||||||
|
mv "/opt/leantime/config/sample.env" "/opt/leantime/config/.env"
|
||||||
|
sed -i -e "s|^LEAN_DB_DATABASE.*|LEAN_DB_DATABASE = '$DB_NAME'|" \
|
||||||
|
-e "s|^LEAN_DB_USER.*|LEAN_DB_USER = '$DB_USER'|" \
|
||||||
|
-e "s|^LEAN_DB_PASSWORD.*|LEAN_DB_PASSWORD = '$DB_PASS'|" \
|
||||||
|
-e "s|^LEAN_SESSION_PASSWORD.*|LEAN_SESSION_PASSWORD = '$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)'|" \
|
||||||
|
"/opt/leantime/config/.env"
|
||||||
|
$STD a2enmod -q proxy_fcgi setenvif rewrite
|
||||||
|
$STD a2enconf -q "php8.4-fpm"
|
||||||
|
sed -i -e "s/^;extension.\(curl\|fileinfo\|gd\|intl\|ldap\|mbstring\|exif\|mysqli\|odbc\|openssl\|pdo_mysql\)/extension=\1/g" "/etc/php/8.4/apache2/php.ini"
|
||||||
|
systemctl restart apache2
|
||||||
|
msg_ok "Setup leantime"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD apt-get -y autoremove
|
||||||
|
$STD apt-get -y autoclean
|
||||||
|
msg_ok "Cleaned"
|
||||||
@@ -15,12 +15,10 @@ update_os
|
|||||||
|
|
||||||
msg_info "Installing Mosquitto MQTT Broker"
|
msg_info "Installing Mosquitto MQTT Broker"
|
||||||
source /etc/os-release
|
source /etc/os-release
|
||||||
curl -fsSL http://repo.mosquitto.org/debian/mosquitto-repo.gpg >/usr/share/keyrings/mosquitto-repo.gpg.key
|
|
||||||
chmod go+r /usr/share/keyrings/mosquitto-repo.gpg.key
|
|
||||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/mosquitto-repo.gpg.key] http://repo.mosquitto.org/debian ${VERSION_CODENAME} main" >/etc/apt/sources.list.d/mosquitto.list
|
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get -y install mosquitto
|
$STD apt-get -y install mosquitto
|
||||||
$STD apt-get -y install mosquitto-clients
|
$STD apt-get -y install mosquitto-clients
|
||||||
|
|
||||||
cat <<EOF >/etc/mosquitto/conf.d/default.conf
|
cat <<EOF >/etc/mosquitto/conf.d/default.conf
|
||||||
allow_anonymous false
|
allow_anonymous false
|
||||||
persistence true
|
persistence true
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ RELEASE=$(curl -fsSL https://api.github.com/repos/netbox-community/netbox/releas
|
|||||||
curl -fsSL "https://github.com/netbox-community/netbox/archive/refs/tags/v${RELEASE}.zip" -o "v${RELEASE}.zip"
|
curl -fsSL "https://github.com/netbox-community/netbox/archive/refs/tags/v${RELEASE}.zip" -o "v${RELEASE}.zip"
|
||||||
$STD unzip "v${RELEASE}.zip"
|
$STD unzip "v${RELEASE}.zip"
|
||||||
mv /opt/netbox-"${RELEASE}"/ /opt/netbox
|
mv /opt/netbox-"${RELEASE}"/ /opt/netbox
|
||||||
|
mkdir -p /opt/netbox/netbox/media
|
||||||
|
|
||||||
$STD adduser --system --group netbox
|
$STD adduser --system --group netbox
|
||||||
chown --recursive netbox /opt/netbox/netbox/media/
|
chown --recursive netbox /opt/netbox/netbox/media/
|
||||||
|
|||||||
35
install/resiliosync-install.sh
Normal file
35
install/resiliosync-install.sh
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
|
# Author: David Bennett (dbinit)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://www.resilio.com/sync
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
msg_info "Setting up Resilio Sync Repository"
|
||||||
|
curl -fsSL "https://linux-packages.resilio.com/resilio-sync/key.asc" >/etc/apt/trusted.gpg.d/resilio-sync.asc
|
||||||
|
echo "deb [signed-by=/etc/apt/trusted.gpg.d/resilio-sync.asc] http://linux-packages.resilio.com/resilio-sync/deb resilio-sync non-free" >/etc/apt/sources.list.d/resilio-sync.list
|
||||||
|
$STD apt-get update
|
||||||
|
msg_ok "Resilio Sync Repository Setup"
|
||||||
|
|
||||||
|
msg_info "Installing Resilio Sync"
|
||||||
|
$STD apt-get install -y resilio-sync
|
||||||
|
sed -i "s/127.0.0.1:8888/0.0.0.0:8888/g" /etc/resilio-sync/config.json
|
||||||
|
systemctl enable -q resilio-sync
|
||||||
|
systemctl restart resilio-sync
|
||||||
|
msg_ok "Installed Resilio Sync"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
|
||||||
|
msg_info "Cleaning up"
|
||||||
|
$STD apt-get -y autoremove
|
||||||
|
$STD apt-get -y autoclean
|
||||||
|
msg_ok "Cleaned"
|
||||||
@@ -62,6 +62,7 @@ server {
|
|||||||
listen 80;
|
listen 80;
|
||||||
root /opt/snipe-it/public;
|
root /opt/snipe-it/public;
|
||||||
server_name $IPADDRESS;
|
server_name $IPADDRESS;
|
||||||
|
client_max_body_size 100M;
|
||||||
index index.php;
|
index index.php;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ $STD apt-get install -y \
|
|||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="20" setup_nodejs
|
NODE_VERSION="20" setup_nodejs
|
||||||
fetch_and_deploy_gh_release "tududi" "chrisvel/tududi"
|
fetch_and_deploy_gh_release "tududi" "chrisvel/tududi" "tarball" "v0.80" "/opt/tududi"
|
||||||
|
|
||||||
msg_info "Configuring Tududi"
|
msg_info "Configuring Tududi"
|
||||||
cd /opt/tududi
|
cd /opt/tududi
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ fetch_and_deploy_gh_release "wizarr" "wizarrrr/wizarr"
|
|||||||
|
|
||||||
msg_info "Configure ${APPLICATION}"
|
msg_info "Configure ${APPLICATION}"
|
||||||
cd /opt/wizarr
|
cd /opt/wizarr
|
||||||
/usr/local/bin/uv -q sync --locked
|
$STD /usr/local/bin/uv lock
|
||||||
$STD /usr/local/bin/uv -q run pybabel compile -d app/translations
|
$STD /usr/local/bin/uv sync --locked
|
||||||
|
$STD /usr/local/bin/uv run pybabel compile -d app/translations
|
||||||
$STD npm --prefix app/static install
|
$STD npm --prefix app/static install
|
||||||
$STD npm --prefix app/static run build:css
|
$STD npm --prefix app/static run build:css
|
||||||
mkdir -p ./.cache
|
mkdir -p ./.cache
|
||||||
$STD /usr/local/bin/uv -q run flask db upgrade
|
$STD /usr/local/bin/uv run flask db upgrade
|
||||||
msg_ok "Configure ${APPLICATION}"
|
msg_ok "Configure ${APPLICATION}"
|
||||||
|
|
||||||
msg_info "Creating env, start script and service"
|
msg_info "Creating env, start script and service"
|
||||||
|
|||||||
@@ -41,39 +41,37 @@ function msg_ok() {
|
|||||||
|
|
||||||
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
||||||
|
|
||||||
|
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||||
|
# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0 (NOT 9.1+)
|
||||||
pve_check() {
|
pve_check() {
|
||||||
if ! command -v pveversion >/dev/null 2>&1; then
|
|
||||||
msg_error "This script can only be run on a Proxmox VE host."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local PVE_VER
|
local PVE_VER
|
||||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||||
|
|
||||||
# Proxmox VE 8.x: allow 8.0 – 8.9
|
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||||
if [[ "$PVE_VER" =~ ^9\.([0-9]+)(\.[0-9]+)?$ ]]; then
|
if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
|
||||||
local MINOR="${BASH_REMATCH[1]}"
|
local MINOR="${BASH_REMATCH[1]}"
|
||||||
if ((MINOR != 0)); then
|
if ((MINOR < 0 || MINOR > 9)); then
|
||||||
msg_error "Unsupported Proxmox VE version: $PVE_VER"
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
msg_error "Supported versions: 8.0 – 8.9 or 9.0.x"
|
msg_error "Supported: Proxmox VE version 8.0 – 8.9"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Proxmox VE 9.x: allow only 9.0
|
# Check for Proxmox VE 9.x: allow ONLY 9.0
|
||||||
if [[ "$PVE_VER" =~ ^9\.([0-9]+)$ ]]; then
|
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
||||||
local MINOR="${BASH_REMATCH[1]}"
|
local MINOR="${BASH_REMATCH[1]}"
|
||||||
if ((MINOR != 0)); then
|
if ((MINOR != 0)); then
|
||||||
msg_error "Unsupported Proxmox VE version: $PVE_VER"
|
msg_error "This version of Proxmox VE is not yet supported."
|
||||||
msg_error "Supported versions: 8.0 – 8.9 or 9.0"
|
msg_error "Supported: Proxmox VE version 9.0"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_error "Unsupported Proxmox VE version: $PVE_VER"
|
# All other unsupported versions
|
||||||
msg_error "Supported versions: 8.0 – 8.9 or 9.0"
|
msg_error "This version of Proxmox VE is not supported."
|
||||||
|
msg_error "Supported versions: Proxmox VE 8.0 – 8.x or 9.0"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -514,7 +514,42 @@ post_routines_common() {
|
|||||||
yes)
|
yes)
|
||||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Support Subscriptions" "Supporting the software's development team is essential. Check their official website's Support Subscriptions for pricing. Without their dedicated work, we wouldn't have this exceptional software." 10 58
|
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Support Subscriptions" "Supporting the software's development team is essential. Check their official website's Support Subscriptions for pricing. Without their dedicated work, we wouldn't have this exceptional software." 10 58
|
||||||
msg_info "Disabling subscription nag"
|
msg_info "Disabling subscription nag"
|
||||||
echo "DPkg::Post-Invoke { \"if [ -s /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js ] && ! grep -q -F 'NoMoreNagging' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; then echo 'Removing subscription nag from UI...'; sed -i '/data\.status/{s/\\!//;s/active/NoMoreNagging/}' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; fi\" };" >/etc/apt/apt.conf.d/no-nag-script
|
# Create external script, this is needed because DPkg::Post-Invoke is fidly with quote interpretation
|
||||||
|
cat >/usr/local/bin/pve-remove-nag.sh <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
WEB_JS=/usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
|
||||||
|
if [ -s "$WEB_JS" ] && ! grep -q NoMoreNagging "$WEB_JS"; then
|
||||||
|
echo "Patching Web UI nag..."
|
||||||
|
sed -i -e "/data\.status/ s/!//" -e "/data\.status/ s/active/NoMoreNagging/" "$WEB_JS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MOBILE_TPL=/usr/share/pve-yew-mobile-gui/index.html.tpl
|
||||||
|
MARKER="<!-- MANAGED BLOCK FOR MOBILE NAG -->"
|
||||||
|
if [ -f "$MOBILE_TPL" ] && ! grep -q "$MARKER" "$MOBILE_TPL"; then
|
||||||
|
echo "Patching Mobile UI nag..."
|
||||||
|
printf "%s\n" \
|
||||||
|
"$MARKER" \
|
||||||
|
"<script>" \
|
||||||
|
" function watchAndRemoveDialog() {" \
|
||||||
|
" const observer = new MutationObserver(() => {" \
|
||||||
|
" const dialog = document.querySelector('dialog[aria-label=\"No valid subscription\"]');" \
|
||||||
|
" if (dialog) { dialog.remove(); console.log('Removed dialog: No valid subscription'); observer.disconnect(); }" \
|
||||||
|
" });" \
|
||||||
|
" observer.observe(document.body, { childList: true, subtree: true });" \
|
||||||
|
" }" \
|
||||||
|
" setTimeout(watchAndRemoveDialog, 100);" \
|
||||||
|
"</script>" \
|
||||||
|
"" >> "$MOBILE_TPL"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 /usr/local/bin/pve-remove-nag.sh
|
||||||
|
|
||||||
|
cat >/etc/apt/apt.conf.d/no-nag-script <<'EOF'
|
||||||
|
DPkg::Post-Invoke { "/usr/local/bin/pve-remove-nag.sh"; };
|
||||||
|
EOF
|
||||||
|
chmod 644 /etc/apt/apt.conf.d/no-nag-script
|
||||||
|
|
||||||
msg_ok "Disabled subscription nag (Delete browser cache)"
|
msg_ok "Disabled subscription nag (Delete browser cache)"
|
||||||
;;
|
;;
|
||||||
no)
|
no)
|
||||||
|
|||||||
Reference in New Issue
Block a user