mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-03-18 16:02:59 +01:00
Compare commits
45 Commits
add-script
...
refactor/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d03d8c622 | ||
|
|
8b4f0f60e1 | ||
|
|
bd91c4d07f | ||
|
|
6bb264491c | ||
|
|
852e557b1b | ||
|
|
c5caca97fd | ||
|
|
dff876fb5c | ||
|
|
02e7e5af8d | ||
|
|
0f4bfc0b5a | ||
|
|
152be10741 | ||
|
|
341489ea3f | ||
|
|
ee7829496f | ||
|
|
b67cbc1585 | ||
|
|
bf17edcc89 | ||
|
|
8aa4e5b8cb | ||
|
|
7c770e2ee7 | ||
|
|
6d15a22d94 | ||
|
|
3db4ac1050 | ||
|
|
16dfad5c77 | ||
|
|
5197d759d7 | ||
|
|
c073286d53 | ||
|
|
cbaba2f133 | ||
|
|
48afb6c017 | ||
|
|
37f2e0242d | ||
|
|
7c62147a00 | ||
|
|
7d11f9acd6 | ||
|
|
55a877a3e2 | ||
|
|
27c9d7fd07 | ||
|
|
c907e10334 | ||
|
|
804c462dd3 | ||
|
|
9df9a2831e | ||
|
|
4aa83fd98e | ||
|
|
6747f0c340 | ||
|
|
8ef2c445c8 | ||
|
|
e4a7ed6965 | ||
|
|
c69dae5326 | ||
|
|
fee4617802 | ||
|
|
339301947b | ||
|
|
5df3c2cd34 | ||
|
|
6832e23ff1 | ||
|
|
d08ba7a0c4 | ||
|
|
780c0e055f | ||
|
|
c55d0784e2 | ||
|
|
2080603464 | ||
|
|
13aea57207 |
53
CHANGELOG.md
53
CHANGELOG.md
@@ -423,12 +423,63 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
</details>
|
||||
|
||||
## 2026-03-16
|
||||
## 2026-03-18
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Split-Pro ([#12975](https://github.com/community-scripts/ProxmoxVE/pull/12975))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Paperless-NGX: increase default RAM to 3GB [@MickLesk](https://github.com/MickLesk) ([#13018](https://github.com/community-scripts/ProxmoxVE/pull/13018))
|
||||
- Plex: restart service after update to apply new version [@MickLesk](https://github.com/MickLesk) ([#13017](https://github.com/community-scripts/ProxmoxVE/pull/13017))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools: centralize GPU group setup via setup_hwaccel [@MickLesk](https://github.com/MickLesk) ([#13044](https://github.com/community-scripts/ProxmoxVE/pull/13044))
|
||||
- Termix: add guacd build and systemd integration [@MickLesk](https://github.com/MickLesk) ([#12999](https://github.com/community-scripts/ProxmoxVE/pull/12999))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Refactor: Jellyfin repo, ffmpeg package and symlinks [@MickLesk](https://github.com/MickLesk) ([#13045](https://github.com/community-scripts/ProxmoxVE/pull/13045))
|
||||
- pve-scripts-local: Increase default disk size from 4GB to 10GB [@MickLesk](https://github.com/MickLesk) ([#13009](https://github.com/community-scripts/ProxmoxVE/pull/13009))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func: Implement check_for_gh_tag function [@MickLesk](https://github.com/MickLesk) ([#12998](https://github.com/community-scripts/ProxmoxVE/pull/12998))
|
||||
- tools.func: Implement fetch_and_deploy_gh_tag function [@MickLesk](https://github.com/MickLesk) ([#13000](https://github.com/community-scripts/ProxmoxVE/pull/13000))
|
||||
|
||||
## 2026-03-17
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Gluetun: add OpenVPN process user and cleanup stale config [@MickLesk](https://github.com/MickLesk) ([#13016](https://github.com/community-scripts/ProxmoxVE/pull/13016))
|
||||
- Frigate: check OpenVino model files exist before configuring detector and use curl_with_retry instead of default wget [@MickLesk](https://github.com/MickLesk) ([#13019](https://github.com/community-scripts/ProxmoxVE/pull/13019))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- tools.func: Update `create_self_signed_cert()` [@tremor021](https://github.com/tremor021) ([#13008](https://github.com/community-scripts/ProxmoxVE/pull/13008))
|
||||
|
||||
## 2026-03-16
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Gluetun ([#12976](https://github.com/community-scripts/ProxmoxVE/pull/12976))
|
||||
- Anytype-Server ([#12974](https://github.com/community-scripts/ProxmoxVE/pull/12974))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Immich: use gcc-13 for compilation & add uv python pre-install with retry logic [@MickLesk](https://github.com/MickLesk) ([#12935](https://github.com/community-scripts/ProxmoxVE/pull/12935))
|
||||
- Tautulli: add setuptools<81 constraint to update script [@MickLesk](https://github.com/MickLesk) ([#12959](https://github.com/community-scripts/ProxmoxVE/pull/12959))
|
||||
- Seerr: add missing build deps [@MickLesk](https://github.com/MickLesk) ([#12960](https://github.com/community-scripts/ProxmoxVE/pull/12960))
|
||||
- fix: yubal update [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12961](https://github.com/community-scripts/ProxmoxVE/pull/12961))
|
||||
|
||||
67
ct/anytype-server.sh
Normal file
67
ct/anytype-server.sh
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://anytype.io
|
||||
|
||||
APP="Anytype-Server"
|
||||
var_tags="${var_tags:-notes;productivity;sync}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-4096}"
|
||||
var_disk="${var_disk:-16}"
|
||||
var_os="${var_os:-ubuntu}"
|
||||
var_version="${var_version:-24.04}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -f /opt/anytype/any-sync-bundle ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_release "anytype" "grishy/any-sync-bundle"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop anytype
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Backing up Data"
|
||||
cp -r /opt/anytype/data /opt/anytype_data_backup
|
||||
msg_ok "Backed up Data"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "anytype" "grishy/any-sync-bundle" "prebuild" "latest" "/opt/anytype" "any-sync-bundle_*_linux_amd64.tar.gz"
|
||||
chmod +x /opt/anytype/any-sync-bundle
|
||||
|
||||
msg_info "Restoring Data"
|
||||
cp -r /opt/anytype_data_backup/. /opt/anytype/data
|
||||
rm -rf /opt/anytype_data_backup
|
||||
msg_ok "Restored Data"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start anytype
|
||||
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}:33010${CL}"
|
||||
echo -e "${INFO}${YW} Client config file:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}/opt/anytype/data/client-config.yml${CL}"
|
||||
6
ct/headers/anytype-server
Normal file
6
ct/headers/anytype-server
Normal file
@@ -0,0 +1,6 @@
|
||||
___ __ _____
|
||||
/ | ____ __ __/ /___ ______ ___ / ___/___ ______ _____ _____
|
||||
/ /| | / __ \/ / / / __/ / / / __ \/ _ \______\__ \/ _ \/ ___/ | / / _ \/ ___/
|
||||
/ ___ |/ / / / /_/ / /_/ /_/ / /_/ / __/_____/__/ / __/ / | |/ / __/ /
|
||||
/_/ |_/_/ /_/\__, /\__/\__, / .___/\___/ /____/\___/_/ |___/\___/_/
|
||||
/____/ /____/_/
|
||||
6
ct/headers/gluetun
Normal file
6
ct/headers/gluetun
Normal file
@@ -0,0 +1,6 @@
|
||||
________ __
|
||||
/ ____/ /_ _____ / /___ ______
|
||||
/ / __/ / / / / _ \/ __/ / / / __ \
|
||||
/ /_/ / / /_/ / __/ /_/ /_/ / / / /
|
||||
\____/_/\__,_/\___/\__/\__,_/_/ /_/
|
||||
|
||||
6
ct/headers/split-pro
Normal file
6
ct/headers/split-pro
Normal file
@@ -0,0 +1,6 @@
|
||||
_____ ___ __ ____
|
||||
/ ___/____ / (_) /_ / __ \_________
|
||||
\__ \/ __ \/ / / __/_____/ /_/ / ___/ __ \
|
||||
___/ / /_/ / / / /_/_____/ ____/ / / /_/ /
|
||||
/____/ .___/_/_/\__/ /_/ /_/ \____/
|
||||
/_/
|
||||
35
ct/immich.sh
35
ct/immich.sh
@@ -76,7 +76,7 @@ EOF
|
||||
SOURCE_DIR=${STAGING_DIR}/image-source
|
||||
cd /tmp
|
||||
if [[ -f ~/.intel_version ]]; then
|
||||
curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile
|
||||
curl_with_retry "https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile" "Dockerfile"
|
||||
readarray -t INTEL_URLS < <(
|
||||
sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $3}'
|
||||
sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}'
|
||||
@@ -85,7 +85,7 @@ EOF
|
||||
if [[ "$INTEL_RELEASE" != "$(cat ~/.intel_version)" ]]; then
|
||||
msg_info "Updating Intel iGPU dependencies"
|
||||
for url in "${INTEL_URLS[@]}"; do
|
||||
curl -fsSLO "$url"
|
||||
curl_with_retry "$url" "$(basename "$url")"
|
||||
done
|
||||
$STD apt-mark unhold libigdgmm12
|
||||
$STD apt install -y --allow-downgrades ./libigdgmm12*.deb
|
||||
@@ -133,7 +133,7 @@ EOF
|
||||
$STD sudo -u postgres psql -d immich -c "REINDEX INDEX face_index;"
|
||||
$STD sudo -u postgres psql -d immich -c "REINDEX INDEX clip_index;"
|
||||
fi
|
||||
ensure_dependencies ccache
|
||||
ensure_dependencies ccache gcc-13 g++-13
|
||||
|
||||
INSTALL_DIR="/opt/${APP}"
|
||||
UPLOAD_DIR="$(sed -n '/^IMMICH_MEDIA_LOCATION/s/[^=]*=//p' /opt/immich/.env)"
|
||||
@@ -166,7 +166,7 @@ EOF
|
||||
|
||||
setup_uv
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "${RELEASE}" "$SRC_DIR"
|
||||
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1]' ${SRC_DIR}/package.json)"
|
||||
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
|
||||
NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
|
||||
|
||||
msg_info "Updating Immich web and microservices"
|
||||
@@ -217,15 +217,36 @@ EOF
|
||||
chown -R immich:immich "$INSTALL_DIR"
|
||||
chown immich:immich ./uv.lock
|
||||
export VIRTUAL_ENV="${ML_DIR}"/ml-venv
|
||||
export UV_HTTP_TIMEOUT=300
|
||||
if [[ -f ~/.openvino ]]; then
|
||||
ML_PYTHON="python3.13"
|
||||
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv python install "${ML_PYTHON}" && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "Python download attempt $attempt failed, retrying..." && sleep 5
|
||||
done
|
||||
msg_ok "Pre-installed Python ${ML_PYTHON}"
|
||||
msg_info "Updating HW-accelerated machine-learning"
|
||||
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p python3.13 --managed-python
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.13 --managed-python
|
||||
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p "${ML_PYTHON}" --managed-python
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
|
||||
done
|
||||
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-x86_64-linux-gnu.so"
|
||||
msg_ok "Updated HW-accelerated machine-learning"
|
||||
else
|
||||
ML_PYTHON="python3.11"
|
||||
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv python install "${ML_PYTHON}" && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "Python download attempt $attempt failed, retrying..." && sleep 5
|
||||
done
|
||||
msg_ok "Pre-installed Python ${ML_PYTHON}"
|
||||
msg_info "Updating machine-learning"
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p python3.11 --managed-python
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -nu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
|
||||
done
|
||||
msg_ok "Updated machine-learning"
|
||||
fi
|
||||
cd "$SRC_DIR"
|
||||
|
||||
@@ -39,14 +39,23 @@ function update_script() {
|
||||
msg_ok "Updated Intel Dependencies"
|
||||
fi
|
||||
|
||||
msg_info "Setting up Jellyfin Repository"
|
||||
setup_deb822_repo \
|
||||
"jellyfin" \
|
||||
"https://repo.jellyfin.org/jellyfin_team.gpg.key" \
|
||||
"https://repo.jellyfin.org/$(get_os_info id)" \
|
||||
"$(get_os_info codename)"
|
||||
msg_ok "Set up Jellyfin Repository"
|
||||
|
||||
msg_info "Updating Jellyfin"
|
||||
ensure_dependencies libjemalloc2
|
||||
if [[ ! -f /usr/lib/libjemalloc.so ]]; then
|
||||
ln -sf /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so
|
||||
fi
|
||||
$STD apt update
|
||||
$STD apt -y upgrade
|
||||
$STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server
|
||||
$STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server jellyfin-ffmpeg7
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe /usr/bin/ffprobe
|
||||
msg_ok "Updated Jellyfin"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
|
||||
@@ -8,7 +8,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
APP="Paperless-ngx"
|
||||
var_tags="${var_tags:-document;management}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_ram="${var_ram:-3072}"
|
||||
var_disk="${var_disk:-12}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
|
||||
@@ -79,6 +79,11 @@ function update_script() {
|
||||
$STD apt update
|
||||
$STD apt install -y plexmediaserver
|
||||
msg_ok "Updated Plex Media Server"
|
||||
|
||||
msg_info "Restarting Plex Media Server"
|
||||
systemctl restart plexmediaserver
|
||||
msg_ok "Restarted Plex Media Server"
|
||||
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -f /etc/systemd/system/homeassistant.service ]]; then
|
||||
if [[ ! -f /etc/containers/systemd/homeassistant.container ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
@@ -9,7 +9,7 @@ APP="PVE-Scripts-Local"
|
||||
var_tags="${var_tags:-pve-scripts-local}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-4096}"
|
||||
var_disk="${var_disk:-4}"
|
||||
var_disk="${var_disk:-10}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
@@ -51,7 +51,7 @@ function update_script() {
|
||||
|
||||
msg_info "Updating Sparky Fitness Backend"
|
||||
cd /opt/sparkyfitness/SparkyFitnessServer
|
||||
$STD npm install --legacy-peer-deps
|
||||
$STD pnpm install
|
||||
msg_ok "Updated Sparky Fitness Backend"
|
||||
|
||||
msg_info "Updating Sparky Fitness Frontend (Patience)"
|
||||
|
||||
68
ct/split-pro.sh
Normal file
68
ct/split-pro.sh
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: johanngrobe
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/oss-apps/split-pro
|
||||
|
||||
APP="Split-Pro"
|
||||
var_tags="${var_tags:-finance;expense-sharing}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-4096}"
|
||||
var_disk="${var_disk:-6}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -d /opt/split-pro ]]; then
|
||||
msg_error "No Split Pro Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_release "split-pro" "oss-apps/split-pro"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop split-pro
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Backing up Data"
|
||||
cp /opt/split-pro/.env /opt/split-pro.env
|
||||
msg_ok "Backed up Data"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "split-pro" "oss-apps/split-pro" "tarball"
|
||||
|
||||
msg_info "Building Application"
|
||||
cd /opt/split-pro
|
||||
$STD pnpm install --frozen-lockfile
|
||||
$STD pnpm build
|
||||
cp /opt/split-pro.env /opt/split-pro/.env
|
||||
rm -f /opt/split-pro.env
|
||||
ln -sf /opt/split-pro_data/uploads /opt/split-pro/uploads
|
||||
$STD pnpm exec prisma migrate deploy
|
||||
msg_ok "Built Application"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start split-pro
|
||||
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}:3000${CL}"
|
||||
116
ct/termix.sh
116
ct/termix.sh
@@ -29,10 +29,116 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_tag "guacd" "apache/guacamole-server"; then
|
||||
msg_info "Stopping guacd"
|
||||
systemctl stop guacd 2>/dev/null || true
|
||||
msg_ok "Stopped guacd"
|
||||
|
||||
ensure_dependencies \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
libtool-bin \
|
||||
uuid-dev \
|
||||
libvncserver-dev \
|
||||
freerdp3-dev \
|
||||
libssh2-1-dev \
|
||||
libtelnet-dev \
|
||||
libwebsockets-dev \
|
||||
libpulse-dev \
|
||||
libvorbis-dev \
|
||||
libwebp-dev \
|
||||
libssl-dev \
|
||||
libpango1.0-dev \
|
||||
libswscale-dev \
|
||||
libavcodec-dev \
|
||||
libavutil-dev \
|
||||
libavformat-dev
|
||||
|
||||
msg_info "Updating Guacamole Server (guacd)"
|
||||
fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "${CHECK_UPDATE_RELEASE}" "/opt/guacamole-server"
|
||||
cd /opt/guacamole-server
|
||||
export CPPFLAGS="-Wno-error=deprecated-declarations"
|
||||
$STD autoreconf -fi
|
||||
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
|
||||
$STD make
|
||||
$STD make install
|
||||
$STD ldconfig
|
||||
cd /opt
|
||||
rm -rf /opt/guacamole-server
|
||||
msg_ok "Updated Guacamole Server (guacd) to ${CHECK_UPDATE_RELEASE}"
|
||||
|
||||
if [[ ! -f /etc/guacamole/guacd.conf ]]; then
|
||||
mkdir -p /etc/guacamole
|
||||
cat <<EOF >/etc/guacamole/guacd.conf
|
||||
[server]
|
||||
bind_host = 127.0.0.1
|
||||
bind_port = 4822
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ ! -f /etc/systemd/system/guacd.service ]] || grep -q "Type=forking" /etc/systemd/system/guacd.service 2>/dev/null; then
|
||||
cat <<EOF >/etc/systemd/system/guacd.service
|
||||
[Unit]
|
||||
Description=Guacamole Proxy Daemon (guacd)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! grep -q "guacd.service" /etc/systemd/system/termix.service 2>/dev/null; then
|
||||
sed -i '/^After=network.target/s/$/ guacd.service/' /etc/systemd/system/termix.service
|
||||
sed -i '/^\[Unit\]/a Wants=guacd.service' /etc/systemd/system/termix.service
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now guacd
|
||||
fi
|
||||
|
||||
if check_for_gh_release "termix" "Termix-SSH/Termix"; then
|
||||
msg_info "Stopping Service"
|
||||
msg_info "Stopping Termix"
|
||||
systemctl stop termix
|
||||
msg_ok "Stopped Service"
|
||||
msg_ok "Stopped Termix"
|
||||
|
||||
msg_info "Migrating Configuration"
|
||||
if [[ ! -f /opt/termix/.env ]]; then
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
fi
|
||||
if ! grep -q "EnvironmentFile" /etc/systemd/system/termix.service 2>/dev/null; then
|
||||
cat <<EOF >/etc/systemd/system/termix.service
|
||||
[Unit]
|
||||
Description=Termix Backend
|
||||
After=network.target guacd.service
|
||||
Wants=guacd.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/termix
|
||||
EnvironmentFile=/opt/termix/.env
|
||||
ExecStart=/usr/bin/node /opt/termix/dist/backend/backend/starter.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
msg_ok "Migrated Configuration"
|
||||
|
||||
msg_info "Backing up Data"
|
||||
cp -r /opt/termix/data /opt/termix_data_backup
|
||||
@@ -95,16 +201,16 @@ function update_script() {
|
||||
sed -i 's|/app/html|/opt/termix/html|g' /etc/nginx/nginx.conf
|
||||
sed -i 's|/app/nginx|/opt/termix/nginx|g' /etc/nginx/nginx.conf
|
||||
sed -i 's|listen ${PORT};|listen 80;|g' /etc/nginx/nginx.conf
|
||||
|
||||
|
||||
nginx -t && systemctl reload nginx
|
||||
msg_ok "Updated Nginx Configuration"
|
||||
else
|
||||
msg_warn "Nginx configuration not updated. If Termix doesn't work, restore from backup or update manually."
|
||||
fi
|
||||
|
||||
msg_info "Starting Service"
|
||||
msg_info "Starting Termix"
|
||||
systemctl start termix
|
||||
msg_ok "Started Service"
|
||||
msg_ok "Started Termix"
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
exit
|
||||
|
||||
81
install/anytype-server-install.sh
Normal file
81
install/anytype-server-install.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://anytype.io
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
setup_mongodb
|
||||
|
||||
msg_info "Configuring MongoDB Replica Set"
|
||||
cat <<EOF >>/etc/mongod.conf
|
||||
|
||||
replication:
|
||||
replSetName: "rs0"
|
||||
EOF
|
||||
systemctl restart mongod
|
||||
sleep 3
|
||||
$STD mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "127.0.0.1:27017"}]})'
|
||||
msg_ok "Configured MongoDB Replica Set"
|
||||
|
||||
msg_info "Installing Redis Stack"
|
||||
setup_deb822_repo \
|
||||
"redis-stack" \
|
||||
"https://packages.redis.io/gpg" \
|
||||
"https://packages.redis.io/deb" \
|
||||
"jammy" \
|
||||
"main"
|
||||
$STD apt install -y redis-stack-server
|
||||
systemctl enable -q --now redis-stack-server
|
||||
msg_ok "Installed Redis Stack"
|
||||
|
||||
fetch_and_deploy_gh_release "anytype" "grishy/any-sync-bundle" "prebuild" "latest" "/opt/anytype" "any-sync-bundle_*_linux_amd64.tar.gz"
|
||||
chmod +x /opt/anytype/any-sync-bundle
|
||||
|
||||
msg_info "Configuring Anytype"
|
||||
mkdir -p /opt/anytype/data/storage
|
||||
cat <<EOF >/opt/anytype/.env
|
||||
ANY_SYNC_BUNDLE_CONFIG=/opt/anytype/data/bundle-config.yml
|
||||
ANY_SYNC_BUNDLE_CLIENT_CONFIG=/opt/anytype/data/client-config.yml
|
||||
ANY_SYNC_BUNDLE_INIT_STORAGE=/opt/anytype/data/storage/
|
||||
ANY_SYNC_BUNDLE_INIT_EXTERNAL_ADDRS=${LOCAL_IP}
|
||||
ANY_SYNC_BUNDLE_INIT_MONGO_URI=mongodb://127.0.0.1:27017/
|
||||
ANY_SYNC_BUNDLE_INIT_REDIS_URI=redis://127.0.0.1:6379/
|
||||
ANY_SYNC_BUNDLE_LOG_LEVEL=info
|
||||
EOF
|
||||
msg_ok "Configured Anytype"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/anytype.service
|
||||
[Unit]
|
||||
Description=Anytype Sync Server (any-sync-bundle)
|
||||
After=network-online.target mongod.service redis-stack-server.service
|
||||
Wants=network-online.target
|
||||
Requires=mongod.service redis-stack-server.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/anytype
|
||||
EnvironmentFile=/opt/anytype/.env
|
||||
ExecStart=/opt/anytype/any-sync-bundle start-bundle
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now anytype
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -35,7 +35,6 @@ setup_hwaccel
|
||||
msg_info "Installing Channels DVR Server (Patience)"
|
||||
cd /opt
|
||||
$STD bash <(curl -fsSL https://getchannels.com/dvr/setup.sh)
|
||||
sed -i -e 's/^sgx:x:104:$/render:x:104:root/' -e 's/^render:x:106:root$/sgx:x:106:/' /etc/group
|
||||
msg_ok "Installed Channels DVR Server"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -13,18 +13,10 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
setup_hwaccel
|
||||
setup_hwaccel "emby"
|
||||
|
||||
fetch_and_deploy_gh_release "emby" "MediaBrowser/Emby.Releases" "binary"
|
||||
|
||||
msg_info "Configuring Emby"
|
||||
if [[ "$CTTYPE" == "0" ]]; then
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:root,emby/' -e 's/^render:x:108:root,emby$/ssl-cert:x:108:/' /etc/group
|
||||
else
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:emby/' -e 's/^render:x:108:emby$/ssl-cert:x:108:/' /etc/group
|
||||
fi
|
||||
msg_ok "Configured Emby"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
|
||||
@@ -146,7 +146,7 @@ ldconfig
|
||||
msg_ok "Built libUSB"
|
||||
|
||||
msg_info "Bootstrapping pip"
|
||||
wget -q https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py
|
||||
curl_with_retry "https://bootstrap.pypa.io/get-pip.py" "/tmp/get-pip.py"
|
||||
sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' /tmp/get-pip.py
|
||||
$STD python3 /tmp/get-pip.py "pip"
|
||||
rm -f /tmp/get-pip.py
|
||||
@@ -169,13 +169,13 @@ NODE_VERSION="20" setup_nodejs
|
||||
|
||||
msg_info "Downloading Inference Models"
|
||||
mkdir -p /models /openvino-model
|
||||
wget -q -O /edgetpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite
|
||||
wget -q -O /models/cpu_model.tflite https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite
|
||||
curl_with_retry "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess_edgetpu.tflite" "/edgetpu_model.tflite"
|
||||
curl_with_retry "https://github.com/google-coral/test_data/raw/release-frogfish/ssdlite_mobiledet_coco_qat_postprocess.tflite" "/models/cpu_model.tflite"
|
||||
cp /opt/frigate/labelmap.txt /labelmap.txt
|
||||
msg_ok "Downloaded Inference Models"
|
||||
|
||||
msg_info "Downloading Audio Model"
|
||||
wget -q -O /tmp/yamnet.tar.gz https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download
|
||||
curl_with_retry "https://www.kaggle.com/api/v1/models/google/yamnet/tfLite/classification-tflite/1/download" "/tmp/yamnet.tar.gz"
|
||||
$STD tar xzf /tmp/yamnet.tar.gz -C /
|
||||
mv /1.tflite /cpu_audio_model.tflite
|
||||
cp /opt/frigate/audio-labelmap.txt /audio-labelmap.txt
|
||||
@@ -205,7 +205,7 @@ msg_ok "Installed OpenVino"
|
||||
|
||||
msg_info "Building OpenVino Model"
|
||||
cd /models
|
||||
wget -q http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz
|
||||
curl_with_retry "http://download.tensorflow.org/models/object_detection/ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz" "ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz"
|
||||
$STD tar -zxf ssdlite_mobilenet_v2_coco_2018_05_09.tar.gz --no-same-owner
|
||||
if python3 /opt/frigate/docker/main/build_ov_model.py &>/dev/null; then
|
||||
mkdir -p /openvino-model
|
||||
@@ -219,7 +219,7 @@ if python3 /opt/frigate/docker/main/build_ov_model.py &>/dev/null; then
|
||||
if [[ -n "$OV_LABELS" ]]; then
|
||||
ln -sf "$OV_LABELS" /openvino-model/coco_91cl_bkgr.txt
|
||||
else
|
||||
wget -q "https://raw.githubusercontent.com/openvinotoolkit/open_model_zoo/master/data/dataset_classes/coco_91cl_bkgr.txt" -O /openvino-model/coco_91cl_bkgr.txt
|
||||
curl_with_retry "https://raw.githubusercontent.com/openvinotoolkit/open_model_zoo/master/data/dataset_classes/coco_91cl_bkgr.txt" "/openvino-model/coco_91cl_bkgr.txt"
|
||||
fi
|
||||
fi
|
||||
sed -i 's/truck/car/g' /openvino-model/coco_91cl_bkgr.txt
|
||||
@@ -246,7 +246,7 @@ msg_info "Configuring Frigate"
|
||||
mkdir -p /config /media/frigate
|
||||
cp -r /opt/frigate/config/. /config
|
||||
|
||||
curl -fsSL "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4" -o "/media/frigate/person-bicycle-car-detection.mp4"
|
||||
curl_with_retry "https://github.com/intel-iot-devkit/sample-videos/raw/master/person-bicycle-car-detection.mp4" "/media/frigate/person-bicycle-car-detection.mp4"
|
||||
|
||||
echo "tmpfs /tmp/cache tmpfs defaults 0 0" >>/etc/fstab
|
||||
|
||||
@@ -289,7 +289,7 @@ detect:
|
||||
enabled: false
|
||||
EOF
|
||||
|
||||
if grep -q -o -m1 -E 'avx[^ ]*|sse4_2' /proc/cpuinfo; then
|
||||
if grep -q -o -m1 -E 'avx[^ ]*|sse4_2' /proc/cpuinfo && [[ -f /openvino-model/ssdlite_mobilenet_v2.xml ]] && [[ -f /openvino-model/coco_91cl_bkgr.txt ]]; then
|
||||
cat <<EOF >>/config/config.yml
|
||||
ffmpeg:
|
||||
hwaccel_args: auto
|
||||
|
||||
@@ -46,6 +46,9 @@ VPN_TYPE=openvpn
|
||||
OPENVPN_CUSTOM_CONFIG=/opt/gluetun-data/custom.ovpn
|
||||
OPENVPN_USER=
|
||||
OPENVPN_PASSWORD=
|
||||
OPENVPN_PROCESS_USER=root
|
||||
PUID=0
|
||||
PGID=0
|
||||
HTTP_CONTROL_SERVER_ADDRESS=:8000
|
||||
HTTPPROXY=off
|
||||
SHADOWSOCKS=off
|
||||
@@ -76,6 +79,7 @@ User=root
|
||||
WorkingDirectory=/opt/gluetun-data
|
||||
EnvironmentFile=/opt/gluetun-data/.env
|
||||
UnsetEnvironment=USER
|
||||
ExecStartPre=/bin/sh -c 'rm -f /etc/openvpn/target.ovpn'
|
||||
ExecStart=/usr/local/bin/gluetun
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
@@ -32,13 +32,13 @@ if [ -d /dev/dri ]; then
|
||||
$STD apt install -y --no-install-recommends patchelf
|
||||
tmp_dir=$(mktemp -d)
|
||||
$STD pushd "$tmp_dir"
|
||||
curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile
|
||||
curl_with_retry "https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile" "Dockerfile"
|
||||
readarray -t INTEL_URLS < <(
|
||||
sed -n "/intel-[igc|opencl]/p" ./Dockerfile | awk '{print $3}'
|
||||
sed -n "/libigdgmm12/p" ./Dockerfile | awk '{print $3}'
|
||||
)
|
||||
for url in "${INTEL_URLS[@]}"; do
|
||||
curl -fsSLO "$url"
|
||||
curl_with_retry "$url" "$(basename "$url")"
|
||||
done
|
||||
$STD apt install -y ./libigdgmm12*.deb
|
||||
rm ./libigdgmm12*.deb
|
||||
@@ -154,6 +154,10 @@ sed -i "s/^#shared_preload.*/shared_preload_libraries = 'vchord.so'/" /etc/postg
|
||||
systemctl restart postgresql.service
|
||||
PG_DB_NAME="immich" PG_DB_USER="immich" PG_DB_GRANT_SUPERUSER="true" PG_DB_SKIP_ALTER_ROLE="true" setup_postgresql_db
|
||||
|
||||
msg_info "Installing GCC-13 (available as fallback compiler)"
|
||||
$STD apt install -y gcc-13 g++-13
|
||||
msg_ok "Installed GCC-13"
|
||||
|
||||
msg_warn "Compiling Custom Photo-processing Libraries (can take anywhere from 15min to 2h)"
|
||||
LD_LIBRARY_PATH=/usr/local/lib
|
||||
export LD_RUN_PATH=/usr/local/lib
|
||||
@@ -290,7 +294,7 @@ GEO_DIR="${INSTALL_DIR}/geodata"
|
||||
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
|
||||
|
||||
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v2.5.6" "$SRC_DIR"
|
||||
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1]' ${SRC_DIR}/package.json)"
|
||||
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
|
||||
NODE_VERSION="24" NODE_MODULE="pnpm@${PNPM_VERSION}" setup_nodejs
|
||||
|
||||
msg_info "Installing Immich (patience)"
|
||||
@@ -340,15 +344,36 @@ cd "$SRC_DIR"/machine-learning
|
||||
$STD useradd -U -s /usr/sbin/nologin -r -M -d "$INSTALL_DIR" immich
|
||||
mkdir -p "$ML_DIR" && chown -R immich:immich "$INSTALL_DIR"
|
||||
export VIRTUAL_ENV="${ML_DIR}/ml-venv"
|
||||
export UV_HTTP_TIMEOUT=300
|
||||
if [[ -f ~/.openvino ]]; then
|
||||
ML_PYTHON="python3.13"
|
||||
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv python install "${ML_PYTHON}" && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "Python download attempt $attempt failed, retrying..." && sleep 5
|
||||
done
|
||||
msg_ok "Pre-installed Python ${ML_PYTHON}"
|
||||
msg_info "Installing HW-accelerated machine-learning"
|
||||
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p python3.13 --managed-python
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p python3.13 --managed-python
|
||||
$STD uv add --no-sync --optional openvino onnxruntime-openvino==1.24.1 --active -n -p "${ML_PYTHON}" --managed-python
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -nu immich uv sync --extra openvino --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
|
||||
done
|
||||
patchelf --clear-execstack "${VIRTUAL_ENV}/lib/python3.13/site-packages/onnxruntime/capi/onnxruntime_pybind11_state.cpython-313-x86_64-linux-gnu.so"
|
||||
msg_ok "Installed HW-accelerated machine-learning"
|
||||
else
|
||||
ML_PYTHON="python3.11"
|
||||
msg_info "Pre-installing Python ${ML_PYTHON} for machine-learning"
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv python install "${ML_PYTHON}" && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "Python download attempt $attempt failed, retrying..." && sleep 5
|
||||
done
|
||||
msg_ok "Pre-installed Python ${ML_PYTHON}"
|
||||
msg_info "Installing machine-learning"
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV -nu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p python3.11 --managed-python
|
||||
for attempt in $(seq 1 3); do
|
||||
$STD sudo --preserve-env=VIRTUAL_ENV,UV_HTTP_TIMEOUT -nu immich uv sync --extra cpu --no-dev --active --link-mode copy -n -p "${ML_PYTHON}" --managed-python && break
|
||||
[[ $attempt -lt 3 ]] && msg_warn "uv sync attempt $attempt failed, retrying..." && sleep 10
|
||||
done
|
||||
msg_ok "Installed machine-learning"
|
||||
fi
|
||||
cd "$SRC_DIR"
|
||||
@@ -365,10 +390,10 @@ ln -s "$UPLOAD_DIR" "$ML_DIR"/upload
|
||||
|
||||
msg_info "Installing GeoNames data"
|
||||
cd "$GEO_DIR"
|
||||
curl -fsSLZ -O "https://download.geonames.org/export/dump/admin1CodesASCII.txt" \
|
||||
-O "https://download.geonames.org/export/dump/admin2Codes.txt" \
|
||||
-O "https://download.geonames.org/export/dump/cities500.zip" \
|
||||
-O "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/admin1CodesASCII.txt" "admin1CodesASCII.txt"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/admin2Codes.txt" "admin2Codes.txt"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/cities500.zip" "cities500.zip"
|
||||
curl_with_retry "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson" "ne_10m_admin_0_countries.geojson"
|
||||
unzip -q cities500.zip
|
||||
date --iso-8601=seconds | tr -d "\n" >geodata-date.txt
|
||||
rm cities500.zip
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://jellyfin.org/
|
||||
|
||||
@@ -14,31 +14,30 @@ network_check
|
||||
update_os
|
||||
|
||||
msg_custom "ℹ️" "${GN}" "If NVIDIA GPU passthrough is detected, you'll be asked whether to install drivers in the container"
|
||||
setup_hwaccel
|
||||
setup_hwaccel "jellyfin"
|
||||
|
||||
msg_info "Installing Jellyfin"
|
||||
VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
|
||||
if ! dpkg -s libjemalloc2 >/dev/null 2>&1; then
|
||||
$STD apt install -y libjemalloc2
|
||||
fi
|
||||
msg_info "Installing Dependencies"
|
||||
ensure_dependencies libjemalloc2
|
||||
if [[ ! -f /usr/lib/libjemalloc.so ]]; then
|
||||
ln -sf /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so
|
||||
fi
|
||||
if [[ ! -d /etc/apt/keyrings ]]; then
|
||||
mkdir -p /etc/apt/keyrings
|
||||
fi
|
||||
curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | gpg --dearmor --yes --output /etc/apt/keyrings/jellyfin.gpg
|
||||
cat <<EOF >/etc/apt/sources.list.d/jellyfin.sources
|
||||
Types: deb
|
||||
URIs: https://repo.jellyfin.org/${PCT_OSTYPE}
|
||||
Suites: ${VERSION}
|
||||
Components: main
|
||||
Architectures: amd64
|
||||
Signed-By: /etc/apt/keyrings/jellyfin.gpg
|
||||
EOF
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
$STD apt update
|
||||
$STD apt install -y jellyfin
|
||||
msg_info "Setting up Jellyfin Repository"
|
||||
setup_deb822_repo \
|
||||
"jellyfin" \
|
||||
"https://repo.jellyfin.org/jellyfin_team.gpg.key" \
|
||||
"https://repo.jellyfin.org/$(get_os_info id)" \
|
||||
"$(get_os_info codename)"
|
||||
msg_ok "Set up Jellyfin Repository"
|
||||
|
||||
msg_info "Installing Jellyfin"
|
||||
$STD apt install -y jellyfin jellyfin-ffmpeg7
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe /usr/bin/ffprobe
|
||||
msg_ok "Installed Jellyfin"
|
||||
|
||||
msg_info "Configuring Jellyfin"
|
||||
# Configure log rotation to prevent disk fill (keeps fail2ban compatibility) (PR: #1690 / Issue: #11224)
|
||||
cat <<EOF >/etc/logrotate.d/jellyfin
|
||||
/var/log/jellyfin/*.log {
|
||||
@@ -55,12 +54,7 @@ EOF
|
||||
chown -R jellyfin:adm /etc/jellyfin
|
||||
sleep 10
|
||||
systemctl restart jellyfin
|
||||
if [[ "$CTTYPE" == "0" ]]; then
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:root,jellyfin/' -e 's/^render:x:108:root,jellyfin$/ssl-cert:x:108:/' /etc/group
|
||||
else
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:jellyfin/' -e 's/^render:x:108:jellyfin$/ssl-cert:x:108:/' /etc/group
|
||||
fi
|
||||
msg_ok "Installed Jellyfin"
|
||||
msg_ok "Configured Jellyfin"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
@@ -42,7 +42,7 @@ EOF
|
||||
$STD apt update
|
||||
msg_ok "Set up Intel® Repositories"
|
||||
|
||||
setup_hwaccel
|
||||
setup_hwaccel "ollama"
|
||||
|
||||
msg_info "Installing Intel® Level Zero"
|
||||
# Debian 13+ has newer Level Zero packages in system repos that conflict with Intel repo packages
|
||||
@@ -89,8 +89,6 @@ msg_info "Creating ollama User and Group"
|
||||
if ! id ollama >/dev/null 2>&1; then
|
||||
useradd -r -s /usr/sbin/nologin -U -m -d /usr/share/ollama ollama
|
||||
fi
|
||||
$STD usermod -aG render ollama || true
|
||||
$STD usermod -aG video ollama || true
|
||||
$STD usermod -aG ollama $(id -u -n)
|
||||
msg_ok "Created ollama User and adjusted Groups"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
setup_hwaccel
|
||||
setup_hwaccel "plex"
|
||||
|
||||
msg_info "Setting Up Plex Media Server Repository"
|
||||
setup_deb822_repo \
|
||||
@@ -26,11 +26,6 @@ msg_ok "Set Up Plex Media Server Repository"
|
||||
|
||||
msg_info "Installing Plex Media Server"
|
||||
$STD apt install -y plexmediaserver
|
||||
if [[ "$CTTYPE" == "0" ]]; then
|
||||
sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:root,plex/' -e 's/^render:x:108:root$/ssl-cert:x:108:plex/' /etc/group
|
||||
else
|
||||
sed -i -e 's/^ssl-cert:x:104:plex$/render:x:104:plex/' -e 's/^render:x:108:$/ssl-cert:x:108:/' /etc/group
|
||||
fi
|
||||
msg_ok "Installed Plex Media Server"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -45,32 +45,58 @@ systemctl enable -q --now podman.socket
|
||||
echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf
|
||||
msg_ok "Installed Podman"
|
||||
|
||||
mkdir -p /etc/containers/systemd
|
||||
|
||||
read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
|
||||
podman volume create portainer_data >/dev/null
|
||||
$STD podman run -d \
|
||||
-p 8000:8000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /run/podman/podman.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
cat <<EOF >/etc/containers/systemd/portainer.container
|
||||
[Unit]
|
||||
Description=Portainer Container
|
||||
After=network-online.target
|
||||
|
||||
[Container]
|
||||
Image=docker.io/portainer/portainer-ce:latest
|
||||
ContainerName=portainer
|
||||
PublishPort=8000:8000
|
||||
PublishPort=9443:9443
|
||||
Volume=/run/podman/podman.sock:/var/run/docker.sock
|
||||
Volume=portainer_data:/data
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now portainer
|
||||
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
|
||||
else
|
||||
read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
podman volume create temp >/dev/null
|
||||
podman volume remove temp >/dev/null
|
||||
$STD podman run -d \
|
||||
-p 9001:9001 \
|
||||
--name portainer_agent \
|
||||
--restart=always \
|
||||
-v /run/podman/podman.sock:/var/run/docker.sock \
|
||||
-v /var/lib/containers/storage/volumes:/var/lib/docker/volumes \
|
||||
portainer/agent
|
||||
cat <<EOF >/etc/containers/systemd/portainer-agent.container
|
||||
[Unit]
|
||||
Description=Portainer Agent Container
|
||||
After=network-online.target
|
||||
|
||||
[Container]
|
||||
Image=docker.io/portainer/agent:latest
|
||||
ContainerName=portainer_agent
|
||||
PublishPort=9001:9001
|
||||
Volume=/run/podman/podman.sock:/var/run/docker.sock
|
||||
Volume=/var/lib/containers/storage/volumes:/var/lib/docker/volumes
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now portainer-agent
|
||||
msg_ok "Installed Portainer Agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
fi
|
||||
fi
|
||||
@@ -81,18 +107,28 @@ msg_ok "Pulled Home Assistant Image"
|
||||
|
||||
msg_info "Installing Home Assistant"
|
||||
$STD podman volume create hass_config
|
||||
$STD podman run -d \
|
||||
--name homeassistant \
|
||||
--restart unless-stopped \
|
||||
-v /dev:/dev \
|
||||
-v hass_config:/config \
|
||||
-v /etc/localtime:/etc/localtime:ro \
|
||||
-v /etc/timezone:/etc/timezone:ro \
|
||||
--net=host \
|
||||
homeassistant/home-assistant:stable
|
||||
podman generate systemd \
|
||||
--new --name homeassistant \
|
||||
>/etc/systemd/system/homeassistant.service
|
||||
cat <<EOF >/etc/containers/systemd/homeassistant.container
|
||||
[Unit]
|
||||
Description=Home Assistant Container
|
||||
After=network-online.target
|
||||
|
||||
[Container]
|
||||
Image=docker.io/homeassistant/home-assistant:stable
|
||||
ContainerName=homeassistant
|
||||
Volume=/dev:/dev
|
||||
Volume=hass_config:/config
|
||||
Volume=/etc/localtime:/etc/localtime:ro
|
||||
Volume=/etc/timezone:/etc/timezone:ro
|
||||
Network=host
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
TimeoutStartSec=300
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now homeassistant
|
||||
msg_ok "Installed Home Assistant"
|
||||
|
||||
|
||||
@@ -45,32 +45,58 @@ systemctl enable -q --now podman.socket
|
||||
echo -e 'unqualified-search-registries=["docker.io"]' >>/etc/containers/registries.conf
|
||||
msg_ok "Installed Podman"
|
||||
|
||||
mkdir -p /etc/containers/systemd
|
||||
|
||||
read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
|
||||
podman volume create portainer_data >/dev/null
|
||||
$STD podman run -d \
|
||||
-p 8000:8000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /run/podman/podman.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
cat <<EOF >/etc/containers/systemd/portainer.container
|
||||
[Unit]
|
||||
Description=Portainer Container
|
||||
After=network-online.target
|
||||
|
||||
[Container]
|
||||
Image=docker.io/portainer/portainer-ce:latest
|
||||
ContainerName=portainer
|
||||
PublishPort=8000:8000
|
||||
PublishPort=9443:9443
|
||||
Volume=/run/podman/podman.sock:/var/run/docker.sock
|
||||
Volume=portainer_data:/data
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now portainer
|
||||
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
|
||||
else
|
||||
read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Portainer agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
podman volume create temp >/dev/null
|
||||
podman volume remove temp >/dev/null
|
||||
$STD podman run -d \
|
||||
-p 9001:9001 \
|
||||
--name portainer_agent \
|
||||
--restart=always \
|
||||
-v /run/podman/podman.sock:/var/run/docker.sock \
|
||||
-v /var/lib/containers/storage/volumes:/var/lib/docker/volumes \
|
||||
portainer/agent
|
||||
cat <<EOF >/etc/containers/systemd/portainer-agent.container
|
||||
[Unit]
|
||||
Description=Portainer Agent Container
|
||||
After=network-online.target
|
||||
|
||||
[Container]
|
||||
Image=docker.io/portainer/agent:latest
|
||||
ContainerName=portainer_agent
|
||||
PublishPort=9001:9001
|
||||
Volume=/run/podman/podman.sock:/var/run/docker.sock
|
||||
Volume=/var/lib/containers/storage/volumes:/var/lib/docker/volumes
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now portainer-agent
|
||||
msg_ok "Installed Portainer Agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -47,7 +47,7 @@ msg_ok "Configured Sparky Fitness"
|
||||
|
||||
msg_info "Building Backend"
|
||||
cd /opt/sparkyfitness/SparkyFitnessServer
|
||||
$STD npm install --legacy-peer-deps
|
||||
$STD pnpm install
|
||||
msg_ok "Built Backend"
|
||||
|
||||
msg_info "Building Frontend (Patience)"
|
||||
|
||||
74
install/split-pro-install.sh
Normal file
74
install/split-pro-install.sh
Normal file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: johanngrobe
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/oss-apps/split-pro
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
NODE_VERSION="22" NODE_MODULE="pnpm" setup_nodejs
|
||||
PG_VERSION="17" PG_MODULES="cron" setup_postgresql
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y openssl
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
PG_DB_NAME="splitpro" PG_DB_USER="splitpro" PG_DB_EXTENSIONS="pg_cron" setup_postgresql_db
|
||||
fetch_and_deploy_gh_release "split-pro" "oss-apps/split-pro" "tarball"
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
cd /opt/split-pro
|
||||
$STD pnpm install --frozen-lockfile
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Building Split Pro"
|
||||
cd /opt/split-pro
|
||||
mkdir -p /opt/split-pro_data/uploads
|
||||
ln -sf /opt/split-pro_data/uploads /opt/split-pro/uploads
|
||||
NEXTAUTH_SECRET=$(openssl rand -base64 32)
|
||||
cp .env.example .env
|
||||
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=\"postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}\"|" .env
|
||||
sed -i "s|^NEXTAUTH_SECRET=.*|NEXTAUTH_SECRET=\"${NEXTAUTH_SECRET}\"|" .env
|
||||
sed -i "s|^NEXTAUTH_URL=.*|NEXTAUTH_URL=\"http://${LOCAL_IP}:3000\"|" .env
|
||||
sed -i "s|^NEXTAUTH_URL_INTERNAL=.*|NEXTAUTH_URL_INTERNAL=\"http://localhost:3000\"|" .env
|
||||
sed -i "/^POSTGRES_CONTAINER_NAME=/d" .env
|
||||
sed -i "/^POSTGRES_USER=/d" .env
|
||||
sed -i "/^POSTGRES_PASSWORD=/d" .env
|
||||
sed -i "/^POSTGRES_DB=/d" .env
|
||||
sed -i "/^POSTGRES_PORT=/d" .env
|
||||
$STD pnpm build
|
||||
$STD pnpm exec prisma migrate deploy
|
||||
msg_ok "Built Split Pro"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/split-pro.service
|
||||
[Unit]
|
||||
Description=Split Pro
|
||||
After=network.target postgresql.service
|
||||
Requires=postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/split-pro
|
||||
EnvironmentFile=/opt/split-pro/.env
|
||||
ExecStart=/usr/bin/pnpm start
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now split-pro
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -19,9 +19,41 @@ $STD apt install -y \
|
||||
python3 \
|
||||
nginx \
|
||||
openssl \
|
||||
gettext-base
|
||||
gettext-base \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
libtool-bin \
|
||||
uuid-dev \
|
||||
libvncserver-dev \
|
||||
freerdp3-dev \
|
||||
libssh2-1-dev \
|
||||
libtelnet-dev \
|
||||
libwebsockets-dev \
|
||||
libpulse-dev \
|
||||
libvorbis-dev \
|
||||
libwebp-dev \
|
||||
libssl-dev \
|
||||
libpango1.0-dev \
|
||||
libswscale-dev \
|
||||
libavcodec-dev \
|
||||
libavutil-dev \
|
||||
libavformat-dev
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Building Guacamole Server (guacd)"
|
||||
fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "latest" "/opt/guacamole-server"
|
||||
cd /opt/guacamole-server
|
||||
export CPPFLAGS="-Wno-error=deprecated-declarations"
|
||||
$STD autoreconf -fi
|
||||
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
|
||||
$STD make
|
||||
$STD make install
|
||||
$STD ldconfig
|
||||
cd /opt
|
||||
rm -rf /opt/guacamole-server
|
||||
msg_ok "Built Guacamole Server (guacd)"
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"
|
||||
|
||||
@@ -74,17 +106,46 @@ systemctl reload nginx
|
||||
msg_ok "Configured Nginx"
|
||||
|
||||
msg_info "Creating Service"
|
||||
mkdir -p /etc/guacamole
|
||||
cat <<EOF >/etc/guacamole/guacd.conf
|
||||
[server]
|
||||
bind_host = 127.0.0.1
|
||||
bind_port = 4822
|
||||
EOF
|
||||
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
|
||||
cat <<EOF >/etc/systemd/system/guacd.service
|
||||
[Unit]
|
||||
Description=Guacamole Proxy Daemon (guacd)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat <<EOF >/etc/systemd/system/termix.service
|
||||
[Unit]
|
||||
Description=Termix Backend
|
||||
After=network.target
|
||||
After=network.target guacd.service
|
||||
Wants=guacd.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/termix
|
||||
Environment=NODE_ENV=production
|
||||
Environment=DATA_DIR=/opt/termix/data
|
||||
EnvironmentFile=/opt/termix/.env
|
||||
ExecStart=/usr/bin/node /opt/termix/dist/backend/backend/starter.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
@@ -92,7 +153,7 @@ RestartSec=5
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now termix
|
||||
systemctl enable -q --now guacd termix
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
|
||||
270
misc/tools.func
270
misc/tools.func
@@ -1979,6 +1979,47 @@ extract_version_from_json() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get latest GitHub tag (for repos that only publish tags, not releases).
|
||||
#
|
||||
# Usage:
|
||||
# get_latest_gh_tag "owner/repo" [prefix]
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - GitHub repo (owner/repo)
|
||||
# $2 - Optional prefix filter (e.g., "v" to only match tags starting with "v")
|
||||
#
|
||||
# Returns:
|
||||
# Latest tag name (stdout), or returns 1 on failure
|
||||
# ------------------------------------------------------------------------------
|
||||
get_latest_gh_tag() {
|
||||
local repo="$1"
|
||||
local prefix="${2:-}"
|
||||
local temp_file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
if ! github_api_call "https://api.github.com/repos/${repo}/tags?per_page=50" "$temp_file"; then
|
||||
rm -f "$temp_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local tag=""
|
||||
if [[ -n "$prefix" ]]; then
|
||||
tag=$(jq -r --arg p "$prefix" '[.[] | select(.name | startswith($p))][0].name // empty' "$temp_file")
|
||||
else
|
||||
tag=$(jq -r '.[0].name // empty' "$temp_file")
|
||||
fi
|
||||
|
||||
rm -f "$temp_file"
|
||||
|
||||
if [[ -z "$tag" ]]; then
|
||||
msg_error "No tags found for ${repo}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$tag"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get latest GitHub release version with fallback to tags
|
||||
# Usage: get_latest_github_release "owner/repo" [strip_v] [include_prerelease]
|
||||
@@ -2077,103 +2118,131 @@ verify_gpg_fingerprint() {
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get latest GitHub tag for a repository.
|
||||
# Fetches and deploys a GitHub tag-based source tarball.
|
||||
#
|
||||
# Description:
|
||||
# - Queries the GitHub API for tags (not releases)
|
||||
# - Useful for repos that only create tags, not full releases
|
||||
# - Supports optional prefix filter and version-only extraction
|
||||
# - Returns the latest tag name (printed to stdout)
|
||||
# - Downloads the source tarball for a given tag from GitHub
|
||||
# - Extracts to the target directory
|
||||
# - Writes the version to ~/.<app>
|
||||
#
|
||||
# Usage:
|
||||
# MONGO_VERSION=$(get_latest_gh_tag "mongodb/mongo-tools")
|
||||
# LATEST=$(get_latest_gh_tag "owner/repo" "v") # only tags starting with "v"
|
||||
# LATEST=$(get_latest_gh_tag "owner/repo" "" "true") # strip leading "v"
|
||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server"
|
||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "latest" "/opt/guacamole-server"
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - GitHub repo (owner/repo)
|
||||
# $2 - Tag prefix filter (optional, e.g. "v" or "100.")
|
||||
# $3 - Strip prefix from result (optional, "true" to strip $2 prefix)
|
||||
#
|
||||
# Returns:
|
||||
# 0 on success (tag printed to stdout), 1 on failure
|
||||
# $1 - App name (used for version file ~/.<app>)
|
||||
# $2 - GitHub repo (owner/repo)
|
||||
# $3 - Tag version (default: "latest" → auto-detect via get_latest_gh_tag)
|
||||
# $4 - Target directory (default: /opt/$app)
|
||||
#
|
||||
# Notes:
|
||||
# - Skips tags containing "rc", "alpha", "beta", "dev", "test"
|
||||
# - Sorts by version number (sort -V) to find the latest
|
||||
# - Respects GITHUB_TOKEN for rate limiting
|
||||
# - Supports CLEAN_INSTALL=1 to wipe target before extracting
|
||||
# - For repos that only publish tags, not GitHub Releases
|
||||
# ------------------------------------------------------------------------------
|
||||
get_latest_gh_tag() {
|
||||
local repo="$1"
|
||||
local prefix="${2:-}"
|
||||
local strip_prefix="${3:-false}"
|
||||
fetch_and_deploy_gh_tag() {
|
||||
local app="$1"
|
||||
local repo="$2"
|
||||
local version="${3:-latest}"
|
||||
local target="${4:-/opt/$app}"
|
||||
local app_lc=""
|
||||
app_lc="$(echo "${app,,}" | tr -d ' ')"
|
||||
local version_file="$HOME/.${app_lc}"
|
||||
|
||||
local header_args=()
|
||||
[[ -n "${GITHUB_TOKEN:-}" ]] && header_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
||||
if [[ "$version" == "latest" ]]; then
|
||||
version=$(get_latest_gh_tag "$repo") || {
|
||||
msg_error "Failed to determine latest tag for ${repo}"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
local http_code=""
|
||||
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o /tmp/gh_tags.json \
|
||||
-H 'Accept: application/vnd.github+json' \
|
||||
-H 'X-GitHub-Api-Version: 2022-11-28' \
|
||||
"${header_args[@]}" \
|
||||
"https://api.github.com/repos/${repo}/tags?per_page=100" 2>/dev/null) || true
|
||||
local current_version=""
|
||||
[[ -f "$version_file" ]] && current_version=$(<"$version_file")
|
||||
|
||||
if [[ "$http_code" == "401" ]]; then
|
||||
msg_error "GitHub API authentication failed (HTTP 401)."
|
||||
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
|
||||
msg_error "Your GITHUB_TOKEN appears to be invalid or expired."
|
||||
else
|
||||
msg_error "The repository may require authentication. Try: export GITHUB_TOKEN=\"ghp_your_token\""
|
||||
fi
|
||||
rm -f /tmp/gh_tags.json
|
||||
if [[ "$current_version" == "$version" ]]; then
|
||||
msg_ok "$app is already up-to-date ($version)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local tmpdir
|
||||
tmpdir=$(mktemp -d) || return 1
|
||||
local tarball_url="https://github.com/${repo}/archive/refs/tags/${version}.tar.gz"
|
||||
local filename="${app_lc}-${version}.tar.gz"
|
||||
|
||||
msg_info "Fetching GitHub tag: ${app} (${version})"
|
||||
|
||||
download_file "$tarball_url" "$tmpdir/$filename" || {
|
||||
msg_error "Download failed: $tarball_url"
|
||||
rm -rf "$tmpdir"
|
||||
return 1
|
||||
}
|
||||
|
||||
mkdir -p "$target"
|
||||
if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
|
||||
rm -rf "${target:?}/"*
|
||||
fi
|
||||
|
||||
if [[ "$http_code" == "403" ]]; then
|
||||
msg_error "GitHub API rate limit exceeded (HTTP 403)."
|
||||
msg_error "To increase the limit, export a GitHub token before running the script:"
|
||||
msg_error " export GITHUB_TOKEN=\"ghp_your_token_here\""
|
||||
rm -f /tmp/gh_tags.json
|
||||
tar --no-same-owner -xzf "$tmpdir/$filename" -C "$tmpdir" || {
|
||||
msg_error "Failed to extract tarball"
|
||||
rm -rf "$tmpdir"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
||||
msg_error "GitHub API connection failed (no response)."
|
||||
msg_error "Check your network/DNS: curl -sSL https://api.github.com/rate_limit"
|
||||
rm -f /tmp/gh_tags.json
|
||||
return 1
|
||||
fi
|
||||
local unpack_dir
|
||||
unpack_dir=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d | head -n1)
|
||||
|
||||
if [[ "$http_code" != "200" ]] || [[ ! -s /tmp/gh_tags.json ]]; then
|
||||
msg_error "Unable to fetch tags for ${repo} (HTTP ${http_code})"
|
||||
rm -f /tmp/gh_tags.json
|
||||
return 1
|
||||
fi
|
||||
shopt -s dotglob nullglob
|
||||
cp -r "$unpack_dir"/* "$target/"
|
||||
shopt -u dotglob nullglob
|
||||
|
||||
local tags_json
|
||||
tags_json=$(</tmp/gh_tags.json)
|
||||
rm -f /tmp/gh_tags.json
|
||||
|
||||
# Extract tag names, filter by prefix, exclude pre-release patterns, sort by version
|
||||
local latest=""
|
||||
latest=$(echo "$tags_json" | grep -oP '"name":\s*"\K[^"]+' |
|
||||
{ [[ -n "$prefix" ]] && grep "^${prefix}" || cat; } |
|
||||
grep -viE '(rc|alpha|beta|dev|test|preview|snapshot)' |
|
||||
sort -V | tail -n1)
|
||||
|
||||
if [[ -z "$latest" ]]; then
|
||||
msg_warn "No matching tags found for ${repo}${prefix:+ (prefix: $prefix)}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "$strip_prefix" == "true" && -n "$prefix" ]]; then
|
||||
latest="${latest#"$prefix"}"
|
||||
fi
|
||||
|
||||
echo "$latest"
|
||||
rm -rf "$tmpdir"
|
||||
echo "$version" >"$version_file"
|
||||
msg_ok "Deployed ${app} ${version} to ${target}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Checks for new GitHub tag (for repos without releases).
|
||||
#
|
||||
# Description:
|
||||
# - Uses get_latest_gh_tag to fetch the latest tag
|
||||
# - Compares it to a local cached version (~/.<app>)
|
||||
# - If newer, sets global CHECK_UPDATE_RELEASE and returns 0
|
||||
#
|
||||
# Usage:
|
||||
# if check_for_gh_tag "guacd" "apache/guacamole-server"; then
|
||||
# fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "/opt/guacamole-server"
|
||||
# fi
|
||||
#
|
||||
# Notes:
|
||||
# - For repos that only publish tags, not GitHub Releases
|
||||
# - Same interface as check_for_gh_release
|
||||
# ------------------------------------------------------------------------------
|
||||
check_for_gh_tag() {
|
||||
local app="$1"
|
||||
local repo="$2"
|
||||
local prefix="${3:-}"
|
||||
local app_lc=""
|
||||
app_lc="$(echo "${app,,}" | tr -d ' ')"
|
||||
local current_file="$HOME/.${app_lc}"
|
||||
|
||||
msg_info "Checking for update: ${app}"
|
||||
|
||||
local latest=""
|
||||
latest=$(get_latest_gh_tag "$repo" "$prefix") || return 1
|
||||
|
||||
local current=""
|
||||
[[ -f "$current_file" ]] && current="$(<"$current_file")"
|
||||
|
||||
if [[ -z "$current" || "$current" != "$latest" ]]; then
|
||||
CHECK_UPDATE_RELEASE="$latest"
|
||||
msg_ok "Update available: ${app} ${current:-not installed} → ${latest}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
msg_ok "No update available: ${app} (${latest})"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL FUNCTIONS
|
||||
# ==============================================================================
|
||||
@@ -2519,6 +2588,8 @@ check_for_codeberg_release() {
|
||||
# ------------------------------------------------------------------------------
|
||||
create_self_signed_cert() {
|
||||
local APP_NAME="${1:-${APPLICATION}}"
|
||||
local HOSTNAME="$(hostname -f)"
|
||||
local IP="$(hostname -I | awk '{print $1}')"
|
||||
local APP_NAME_LC=$(echo "${APP_NAME,,}" | tr -d ' ')
|
||||
local CERT_DIR="/etc/ssl/${APP_NAME_LC}"
|
||||
local CERT_KEY="${CERT_DIR}/${APP_NAME_LC}.key"
|
||||
@@ -2536,8 +2607,8 @@ create_self_signed_cert() {
|
||||
|
||||
mkdir -p "$CERT_DIR"
|
||||
$STD openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 \
|
||||
-subj "/CN=${APP_NAME}" \
|
||||
-addext "subjectAltName=DNS:${APP_NAME}" \
|
||||
-subj "/CN=${HOSTNAME}" \
|
||||
-addext "subjectAltName=DNS:${HOSTNAME},DNS:localhost,IP:${IP},IP:127.0.0.1" \
|
||||
-keyout "$CERT_KEY" \
|
||||
-out "$CERT_CRT" || {
|
||||
msg_error "Failed to create self-signed certificate"
|
||||
@@ -4185,6 +4256,8 @@ function setup_gs() {
|
||||
# - NVIDIA requires matching host driver version
|
||||
# ------------------------------------------------------------------------------
|
||||
function setup_hwaccel() {
|
||||
local service_user="${1:-}"
|
||||
|
||||
# Check if user explicitly disabled GPU in advanced settings
|
||||
# ENABLE_GPU is exported from build.func
|
||||
if [[ "${ENABLE_GPU:-no}" == "no" ]]; then
|
||||
@@ -4436,7 +4509,7 @@ function setup_hwaccel() {
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Device Permissions
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
_setup_gpu_permissions "$in_ct"
|
||||
_setup_gpu_permissions "$in_ct" "$service_user"
|
||||
|
||||
cache_installed_version "hwaccel" "1.0"
|
||||
msg_ok "Setup Hardware Acceleration"
|
||||
@@ -4676,16 +4749,9 @@ _setup_rocm() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# AMDGPU driver repository (append to same keyring)
|
||||
{
|
||||
echo ""
|
||||
echo "Types: deb"
|
||||
echo "URIs: https://repo.radeon.com/amdgpu/latest/ubuntu"
|
||||
echo "Suites: ${ROCM_REPO_CODENAME}"
|
||||
echo "Components: main"
|
||||
echo "Architectures: amd64"
|
||||
echo "Signed-By: /etc/apt/keyrings/rocm.gpg"
|
||||
} >>/etc/apt/sources.list.d/rocm.sources
|
||||
# Note: The amdgpu/latest/ubuntu repo (kernel driver packages) is intentionally
|
||||
# omitted — kernel drivers are managed by the Proxmox host, not the LXC container.
|
||||
# Only the ROCm userspace compute stack is needed inside the container.
|
||||
|
||||
# Pin ROCm packages to prefer radeon repo
|
||||
cat <<EOF >/etc/apt/preferences.d/rocm-pin-600
|
||||
@@ -4694,7 +4760,26 @@ Pin: release o=repo.radeon.com
|
||||
Pin-Priority: 600
|
||||
EOF
|
||||
|
||||
$STD apt update || msg_warn "apt update failed (AMD repo may be temporarily unavailable) — continuing anyway"
|
||||
# apt update with retry — repo.radeon.com CDN can be mid-sync (transient size mismatches).
|
||||
# Run with ERR trap disabled so a transient failure does not abort the entire install.
|
||||
local _apt_ok=0
|
||||
for _attempt in 1 2 3; do
|
||||
if (
|
||||
set +e
|
||||
apt-get update -qq 2>&1
|
||||
exit $?
|
||||
) 2>/dev/null; then
|
||||
_apt_ok=1
|
||||
break
|
||||
fi
|
||||
msg_warn "apt update failed (attempt ${_attempt}/3) — AMD repo may be temporarily unavailable, retrying in 30s…"
|
||||
sleep 30
|
||||
done
|
||||
if [[ $_apt_ok -eq 0 ]]; then
|
||||
msg_warn "apt update still failing after 3 attempts — skipping ROCm install"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Install only runtime packages — full 'rocm' meta-package includes 15GB+ dev tools
|
||||
$STD apt install -y rocm-opencl-runtime rocm-hip-runtime rocm-smi-lib 2>/dev/null || {
|
||||
msg_warn "ROCm runtime install failed — trying minimal set"
|
||||
@@ -5058,6 +5143,7 @@ EOF
|
||||
# ══════════════════════════════════════════════════════════════════════════════
|
||||
_setup_gpu_permissions() {
|
||||
local in_ct="$1"
|
||||
local service_user="${2:-}"
|
||||
|
||||
# /dev/dri permissions (Intel/AMD)
|
||||
if [[ "$in_ct" == "0" && -d /dev/dri ]]; then
|
||||
@@ -5124,6 +5210,12 @@ _setup_gpu_permissions() {
|
||||
chmod 666 /dev/kfd 2>/dev/null || true
|
||||
msg_info "AMD ROCm compute device configured"
|
||||
fi
|
||||
|
||||
# Add service user to render and video groups for GPU hardware acceleration
|
||||
if [[ -n "$service_user" ]]; then
|
||||
$STD usermod -aG render "$service_user" 2>/dev/null || true
|
||||
$STD usermod -aG video "$service_user" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user