mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-16 18:23:27 +01:00
Compare commits
1 Commits
main
...
github-act
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b42a8f0a2b |
3
.github/workflows/autolabeler.yml
generated
vendored
3
.github/workflows/autolabeler.yml
generated
vendored
@@ -100,8 +100,7 @@ jobs:
|
|||||||
// If it's an update script PR with json changes and a content label, skip adding website/json
|
// If it's an update script PR with json changes and a content label, skip adding website/json
|
||||||
// The PR should be categorized as update script with the content label
|
// The PR should be categorized as update script with the content label
|
||||||
if (!(hasUpdateScript && hasJson && hasContentLabel)) {
|
if (!(hasUpdateScript && hasJson && hasContentLabel)) {
|
||||||
labelsToAdd.add("website");
|
labelsToAdd.add(hasJson ? "json" : "website");
|
||||||
if (hasJson) labelsToAdd.add("json");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
62
CHANGELOG.md
62
CHANGELOG.md
@@ -404,68 +404,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 2026-02-16
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- RomM ([#11987](https://github.com/community-scripts/ProxmoxVE/pull/11987))
|
|
||||||
- LinkDing ([#11976](https://github.com/community-scripts/ProxmoxVE/pull/11976))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Tududi: Fix sed command for DB_FILE configuration [@tremor021](https://github.com/tremor021) ([#11988](https://github.com/community-scripts/ProxmoxVE/pull/11988))
|
|
||||||
- slskd: fix exit position [@MickLesk](https://github.com/MickLesk) ([#11963](https://github.com/community-scripts/ProxmoxVE/pull/11963))
|
|
||||||
- cryptpad: restore config earlier and run onlyoffice upgrade [@MickLesk](https://github.com/MickLesk) ([#11964](https://github.com/community-scripts/ProxmoxVE/pull/11964))
|
|
||||||
- jellyseerr/overseerr: Migrate update script to Seerr; prompt rerun [@MickLesk](https://github.com/MickLesk) ([#11965](https://github.com/community-scripts/ProxmoxVE/pull/11965))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- core/vm's: ensure script state is sent on script exit [@MickLesk](https://github.com/MickLesk) ([#11991](https://github.com/community-scripts/ProxmoxVE/pull/11991))
|
|
||||||
- Vaultwarden: export VW_VERSION as version number [@MickLesk](https://github.com/MickLesk) ([#11966](https://github.com/community-scripts/ProxmoxVE/pull/11966))
|
|
||||||
- Zabbix: Improve zabbix-agent service detection [@MickLesk](https://github.com/MickLesk) ([#11968](https://github.com/community-scripts/ProxmoxVE/pull/11968))
|
|
||||||
|
|
||||||
### 💾 Core
|
|
||||||
|
|
||||||
- #### ✨ New Features
|
|
||||||
|
|
||||||
- tools.func: ensure /usr/local/bin PATH persists for pct enter sessions [@MickLesk](https://github.com/MickLesk) ([#11970](https://github.com/community-scripts/ProxmoxVE/pull/11970))
|
|
||||||
|
|
||||||
- #### 🔧 Refactor
|
|
||||||
|
|
||||||
- core: remove duplicate error handler from alpine-install.func [@MickLesk](https://github.com/MickLesk) ([#11971](https://github.com/community-scripts/ProxmoxVE/pull/11971))
|
|
||||||
|
|
||||||
### 📂 Github
|
|
||||||
|
|
||||||
- github: add "website" label if "json" changed [@MickLesk](https://github.com/MickLesk) ([#11975](https://github.com/community-scripts/ProxmoxVE/pull/11975))
|
|
||||||
|
|
||||||
### 🌐 Website
|
|
||||||
|
|
||||||
- #### 📝 Script Information
|
|
||||||
|
|
||||||
- Update Wishlist LXC webpage to include reverse proxy info [@summoningpixels](https://github.com/summoningpixels) ([#11973](https://github.com/community-scripts/ProxmoxVE/pull/11973))
|
|
||||||
- Update OpenCloud LXC webpage to include services ports [@summoningpixels](https://github.com/summoningpixels) ([#11969](https://github.com/community-scripts/ProxmoxVE/pull/11969))
|
|
||||||
|
|
||||||
## 2026-02-15
|
|
||||||
|
|
||||||
### 🆕 New Scripts
|
|
||||||
|
|
||||||
- ebusd ([#11942](https://github.com/community-scripts/ProxmoxVE/pull/11942))
|
|
||||||
- add: seer script and migrations [@CrazyWolf13](https://github.com/CrazyWolf13) ([#11930](https://github.com/community-scripts/ProxmoxVE/pull/11930))
|
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
|
||||||
|
|
||||||
- #### 🐞 Bug Fixes
|
|
||||||
|
|
||||||
- Fix seerr URL in jellyseerr script [@lucacome](https://github.com/lucacome) ([#11951](https://github.com/community-scripts/ProxmoxVE/pull/11951))
|
|
||||||
- Fix jellyseer and overseer script replacement [@lucacome](https://github.com/lucacome) ([#11949](https://github.com/community-scripts/ProxmoxVE/pull/11949))
|
|
||||||
- Tautulli: Add setuptools < 81 [@tremor021](https://github.com/tremor021) ([#11943](https://github.com/community-scripts/ProxmoxVE/pull/11943))
|
|
||||||
|
|
||||||
- #### 💥 Breaking Changes
|
|
||||||
|
|
||||||
- Refactor: Patchmon [@vhsdream](https://github.com/vhsdream) ([#11888](https://github.com/community-scripts/ProxmoxVE/pull/11888))
|
|
||||||
|
|
||||||
## 2026-02-14
|
## 2026-02-14
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
RELEASE=$(curl -fsSL https://teamspeak.com/en/downloads/#server | sed -n 's/.*teamspeak3-server_linux_amd64-\([0-9.]*[0-9]\).*/\1/p' | awk 'NR==1')
|
set +o pipefail && RELEASE=$(curl -fsSL https://teamspeak.com/en/downloads/#server | sed -n 's/.*teamspeak3-server_linux_amd64-\([0-9.]*[0-9]\).*/\1/p' | head -1) && set -o pipefail
|
||||||
|
|
||||||
if [ "${RELEASE}" != "$(cat ~/.teamspeak-server)" ] || [ ! -f ~/.teamspeak-server ]; then
|
if [ "${RELEASE}" != "$(cat ~/.teamspeak-server)" ] || [ ! -f ~/.teamspeak-server ]; then
|
||||||
msg_info "Updating ${APP} LXC"
|
msg_info "Updating ${APP} LXC"
|
||||||
|
|||||||
@@ -39,20 +39,17 @@ function update_script() {
|
|||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cryptpad" "cryptpad/cryptpad" "tarball"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cryptpad" "cryptpad/cryptpad" "tarball"
|
||||||
|
|
||||||
msg_info "Restoring configuration"
|
|
||||||
mv /opt/config.js /opt/cryptpad/config/
|
|
||||||
msg_ok "Configuration restored"
|
|
||||||
|
|
||||||
msg_info "Updating CryptaPad"
|
msg_info "Updating CryptaPad"
|
||||||
cd /opt/cryptpad
|
cd /opt/cryptpad
|
||||||
$STD npm ci
|
$STD npm ci
|
||||||
$STD npm run install:components
|
$STD npm run install:components
|
||||||
if [ -f "/opt/cryptpad/install-onlyoffice.sh" ]; then
|
|
||||||
$STD bash /opt/cryptpad/install-onlyoffice.sh --accept-license
|
|
||||||
fi
|
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
msg_ok "Updated CryptaPad"
|
msg_ok "Updated CryptaPad"
|
||||||
|
|
||||||
|
msg_info "Restoring configuration"
|
||||||
|
mv /opt/config.js /opt/cryptpad/config/
|
||||||
|
msg_ok "Configuration restored"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start cryptpad
|
systemctl start cryptpad
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
|
|||||||
50
ct/ebusd.sh
50
ct/ebusd.sh
@@ -1,50 +0,0 @@
|
|||||||
#!/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: Joerg Heinemann (heinemannj)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/john30/ebusd
|
|
||||||
|
|
||||||
APP="ebusd"
|
|
||||||
var_tags="${var_tags:-automation}"
|
|
||||||
var_cpu="${var_cpu:-1}"
|
|
||||||
var_ram="${var_ram:-512}"
|
|
||||||
var_disk="${var_disk:-2}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
if [[ ! -f /etc/default/ebusd ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
if check_for_gh_release "ebusd" "john30/ebusd"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop ebusd
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "ebusd" "john30/ebusd" "binary" "latest" "/opt/ebusd" "ebusd-*_amd64-trixie_mqtt1.deb"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start ebusd
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
__ __
|
|
||||||
___ / /_ __ ___________/ /
|
|
||||||
/ _ \/ __ \/ / / / ___/ __ /
|
|
||||||
/ __/ /_/ / /_/ (__ ) /_/ /
|
|
||||||
\___/_.___/\__,_/____/\__,_/
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
___ __ ___
|
|
||||||
/ (_)___ / /______/ (_)___ ____ _
|
|
||||||
/ / / __ \/ //_/ __ / / __ \/ __ `/
|
|
||||||
/ / / / / / ,< / /_/ / / / / / /_/ /
|
|
||||||
/_/_/_/ /_/_/|_|\__,_/_/_/ /_/\__, /
|
|
||||||
/____/
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
____ __ ___
|
|
||||||
/ __ \____ ____ ___ / |/ /
|
|
||||||
/ /_/ / __ \/ __ `__ \/ /|_/ /
|
|
||||||
/ _, _/ /_/ / / / / / / / / /
|
|
||||||
/_/ |_|\____/_/ /_/ /_/_/ /_/
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
_____
|
|
||||||
/ ___/___ ___ __________
|
|
||||||
\__ \/ _ \/ _ \/ ___/ ___/
|
|
||||||
___/ / __/ __/ / / /
|
|
||||||
/____/\___/\___/_/ /_/
|
|
||||||
|
|
||||||
@@ -29,48 +29,47 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "/opt/jellyseerr/package.json" ]] && [[ "$(grep -m1 '"version"' /opt/jellyseerr/package.json | awk -F'"' '{print $4}')" == "2.7.3" ]]; then
|
if [ "$(node -v | cut -c2-3)" -ne 22 ]; then
|
||||||
echo
|
msg_info "Updating Node.js Repository"
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
|
||||||
echo "Jellyseerr v2.7.3 detected."
|
msg_ok "Updating Node.js Repository"
|
||||||
echo
|
|
||||||
echo "Seerr is the new unified Jellyseerr and Overseerr."
|
|
||||||
echo "More info: https://docs.seerr.dev/blog/seerr-release"
|
|
||||||
echo
|
|
||||||
read -rp "Do you want to migrate to Seerr now? (y/N): " MIGRATE
|
|
||||||
echo
|
|
||||||
if [[ ! "$MIGRATE" =~ ^[Yy]$ ]]; then
|
|
||||||
msg_info "Migration cancelled. Exiting."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Switching update script to Seerr"
|
msg_info "Updating Packages"
|
||||||
cat <<'EOF' >/usr/bin/update
|
$STD apt-get update
|
||||||
#!/usr/bin/env bash
|
$STD apt-get -y upgrade
|
||||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/seerr.sh)"
|
msg_ok "Updating Packages"
|
||||||
EOF
|
fi
|
||||||
chmod +x /usr/bin/update
|
|
||||||
msg_ok "Switched update script to Seerr"
|
cd /opt/jellyseerr
|
||||||
msg_warn "Please type 'update' again to complete the migration"
|
output=$(git pull --no-rebase)
|
||||||
exit
|
|
||||||
|
pnpm_current=$(pnpm --version 2>/dev/null)
|
||||||
|
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/jellyseerr/package.json)
|
||||||
|
|
||||||
|
if [ -z "$pnpm_current" ]; then
|
||||||
|
msg_error "pnpm not found. Installing version $pnpm_desired..."
|
||||||
|
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
||||||
|
elif ! node -e "const semver = require('semver'); process.exit(semver.satisfies('$pnpm_current', '$pnpm_desired') ? 0 : 1)"; then
|
||||||
|
msg_error "Updating pnpm from version $pnpm_current to $pnpm_desired..."
|
||||||
|
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
||||||
|
else
|
||||||
|
msg_ok "pnpm is already installed and satisfies version $pnpm_desired."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Updating Jellyseerr"
|
msg_info "Updating Jellyseerr"
|
||||||
cd /opt/jellyseerr
|
|
||||||
systemctl stop jellyseerr
|
|
||||||
output=$(git pull --no-rebase)
|
|
||||||
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/jellyseerr/package.json)
|
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
|
||||||
if echo "$output" | grep -q "Already up to date."; then
|
if echo "$output" | grep -q "Already up to date."; then
|
||||||
msg_ok "$APP is already up to date."
|
msg_ok "$APP is already up to date."
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
systemctl stop jellyseerr
|
||||||
rm -rf dist .next node_modules
|
rm -rf dist .next node_modules
|
||||||
export CYPRESS_INSTALL_BINARY=0
|
export CYPRESS_INSTALL_BINARY=0
|
||||||
cd /opt/jellyseerr
|
cd /opt/jellyseerr
|
||||||
$STD pnpm install --frozen-lockfile
|
$STD pnpm install --frozen-lockfile
|
||||||
export NODE_OPTIONS="--max-old-space-size=3072"
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
$STD pnpm build
|
$STD pnpm build
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=jellyseerr Service
|
Description=jellyseerr Service
|
||||||
@@ -86,6 +85,7 @@ ExecStart=/usr/bin/node dist/index.js
|
|||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl start jellyseerr
|
systemctl start jellyseerr
|
||||||
msg_ok "Updated Jellyseerr"
|
msg_ok "Updated Jellyseerr"
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/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 (MickLesk)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://linkding.link/
|
|
||||||
|
|
||||||
APP="linkding"
|
|
||||||
var_tags="${var_tags:-bookmarks;management}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-1024}"
|
|
||||||
var_disk="${var_disk:-4}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
|
|
||||||
if [[ ! -d /opt/linkding ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "linkding" "sissbruecker/linkding"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop nginx linkding linkding-tasks
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
msg_info "Backing up Data"
|
|
||||||
cp -r /opt/linkding/data /opt/linkding_data_backup
|
|
||||||
cp /opt/linkding/.env /opt/linkding_env_backup
|
|
||||||
msg_ok "Backed up Data"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "linkding" "sissbruecker/linkding"
|
|
||||||
|
|
||||||
msg_info "Restoring Data"
|
|
||||||
cp -r /opt/linkding_data_backup/. /opt/linkding/data
|
|
||||||
cp /opt/linkding_env_backup /opt/linkding/.env
|
|
||||||
rm -rf /opt/linkding_data_backup /opt/linkding_env_backup
|
|
||||||
ln -sf /usr/lib/x86_64-linux-gnu/mod_icu.so /opt/linkding/libicu.so
|
|
||||||
msg_ok "Restored Data"
|
|
||||||
|
|
||||||
msg_info "Updating LinkDing"
|
|
||||||
cd /opt/linkding
|
|
||||||
rm -f bookmarks/settings/dev.py
|
|
||||||
touch bookmarks/settings/custom.py
|
|
||||||
$STD npm ci
|
|
||||||
$STD npm run build
|
|
||||||
$STD uv sync --no-dev --frozen
|
|
||||||
$STD uv pip install gunicorn
|
|
||||||
set -a && source /opt/linkding/.env && set +a
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py migrate
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py collectstatic --no-input
|
|
||||||
msg_ok "Updated LinkDing"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start nginx linkding linkding-tasks
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated successfully!"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed Successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9090${CL}"
|
|
||||||
@@ -27,33 +27,6 @@ function update_script() {
|
|||||||
msg_error "No ${APP} Installation Found!"
|
msg_error "No ${APP} Installation Found!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "$HOME/.overseerr" ]] && [[ "$(cat "$HOME/.overseerr")" == "1.34.0" ]]; then
|
|
||||||
echo
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "Overseerr v1.34.0 detected."
|
|
||||||
echo
|
|
||||||
echo "Seerr is the new unified Jellyseerr and Overseerr."
|
|
||||||
echo "More info: https://docs.seerr.dev/blog/seerr-release"
|
|
||||||
echo
|
|
||||||
read -rp "Do you want to migrate to Seerr now? (y/N): " MIGRATE
|
|
||||||
echo
|
|
||||||
if [[ ! "$MIGRATE" =~ ^[Yy]$ ]]; then
|
|
||||||
msg_info "Migration cancelled. Exiting."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg_info "Switching update script to Seerr"
|
|
||||||
cat <<'EOF' >/usr/bin/update
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/seerr.sh)"
|
|
||||||
EOF
|
|
||||||
chmod +x /usr/bin/update
|
|
||||||
msg_ok "Switched update script to Seerr"
|
|
||||||
msg_warn "Please type 'update' again to complete the migration"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "overseerr" "sct/overseerr"; then
|
if check_for_gh_release "overseerr" "sct/overseerr"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop overseerr
|
systemctl stop overseerr
|
||||||
|
|||||||
@@ -43,40 +43,22 @@ function update_script() {
|
|||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon"
|
||||||
|
|
||||||
msg_info "Updating PatchMon"
|
msg_info "Updating PatchMon"
|
||||||
VERSION=$(get_latest_github_release "PatchMon/PatchMon")
|
|
||||||
PROTO="$(sed -n '/SERVER_PROTOCOL/s/[^=]*=//p' /opt/backend.env)"
|
|
||||||
HOST="$(sed -n '/SERVER_HOST/s/[^=]*=//p' /opt/backend.env)"
|
|
||||||
[[ "${PROTO:-http}" == "http" ]] && PORT=":3001"
|
|
||||||
sed -i 's/PORT=3399/PORT=3001/' /opt/backend.env
|
|
||||||
sed -i -e "s/VERSION=.*/VERSION=$VERSION/" \
|
|
||||||
-e "\|VITE_API_URL=|s|http.*|${PROTO:-http}://${HOST:-$LOCAL_IP}${PORT:-}/api/v1|" /opt/frontend.env
|
|
||||||
export NODE_ENV=production
|
|
||||||
cd /opt/patchmon
|
cd /opt/patchmon
|
||||||
|
export NODE_ENV=production
|
||||||
|
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
||||||
|
cd /opt/patchmon/backend
|
||||||
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
||||||
cd /opt/patchmon/frontend
|
cd /opt/patchmon/frontend
|
||||||
mv /opt/frontend.env /opt/patchmon/frontend/.env
|
$STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts
|
||||||
$STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev
|
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
cd /opt/patchmon/backend
|
cd /opt/patchmon/backend
|
||||||
mv /opt/backend.env /opt/patchmon/backend/.env
|
mv /opt/backend.env /opt/patchmon/backend/.env
|
||||||
$STD npm run db:generate
|
mv /opt/frontend.env /opt/patchmon/frontend/.env
|
||||||
$STD npx prisma migrate deploy
|
$STD npx prisma migrate deploy
|
||||||
cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf
|
$STD npx prisma generate
|
||||||
sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \
|
|
||||||
-e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \
|
|
||||||
-e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \
|
|
||||||
-e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf
|
|
||||||
ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
|
||||||
$STD nginx -t
|
|
||||||
systemctl restart nginx
|
|
||||||
msg_ok "Updated PatchMon"
|
msg_ok "Updated PatchMon"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
if grep -q '/usr/bin/node' /etc/systemd/system/patchmon-server.service; then
|
|
||||||
sed -i 's|ExecStart=.*|ExecStart=/usr/bin/npm run start|' /etc/systemd/system/patchmon-server.service
|
|
||||||
systemctl daemon-reload
|
|
||||||
fi
|
|
||||||
systemctl start patchmon-server
|
systemctl start patchmon-server
|
||||||
msg_ok "Started Service"
|
msg_ok "Started Service"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
@@ -91,4 +73,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}:3000${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
||||||
|
|||||||
74
ct/romm.sh
74
ct/romm.sh
@@ -1,74 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ) | DevelopmentCats | AlphaLawless
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://romm.app
|
|
||||||
|
|
||||||
APP="RomM"
|
|
||||||
var_tags="${var_tags:-emulation}"
|
|
||||||
var_cpu="${var_cpu:-2}"
|
|
||||||
var_ram="${var_ram:-4096}"
|
|
||||||
var_disk="${var_disk:-20}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
|
|
||||||
if [[ ! -d /opt/romm ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if check_for_gh_release "romm" "rommapp/romm"; then
|
|
||||||
msg_info "Stopping Services"
|
|
||||||
systemctl stop romm-backend romm-worker romm-scheduler romm-watcher
|
|
||||||
msg_ok "Stopped Services"
|
|
||||||
|
|
||||||
msg_info "Backing up configuration"
|
|
||||||
cp /opt/romm/.env /opt/romm/.env.backup
|
|
||||||
msg_ok "Backed up configuration"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm"
|
|
||||||
|
|
||||||
msg_info "Updating ROMM"
|
|
||||||
cp /opt/romm/.env.backup /opt/romm/.env
|
|
||||||
cd /opt/romm
|
|
||||||
$STD uv sync --all-extras
|
|
||||||
cd /opt/romm/backend
|
|
||||||
$STD uv run alembic upgrade head
|
|
||||||
cd /opt/romm/frontend
|
|
||||||
$STD npm install
|
|
||||||
$STD npm run build
|
|
||||||
# Merge static assets into dist folder
|
|
||||||
cp -rf /opt/romm/frontend/assets/* /opt/romm/frontend/dist/assets/
|
|
||||||
mkdir -p /opt/romm/frontend/dist/assets/romm
|
|
||||||
ln -sfn /var/lib/romm/resources /opt/romm/frontend/dist/assets/romm/resources
|
|
||||||
ln -sfn /var/lib/romm/assets /opt/romm/frontend/dist/assets/romm/assets
|
|
||||||
msg_ok "Updated ROMM"
|
|
||||||
|
|
||||||
msg_info "Starting Services"
|
|
||||||
systemctl start romm-backend romm-worker romm-scheduler romm-watcher
|
|
||||||
msg_ok "Started Services"
|
|
||||||
msg_ok "Updated successfully"
|
|
||||||
fi
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
|
|
||||||
start
|
|
||||||
build_container
|
|
||||||
description
|
|
||||||
|
|
||||||
msg_ok "Completed successfully!\n"
|
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
|
||||||
165
ct/seerr.sh
165
ct/seerr.sh
@@ -1,165 +0,0 @@
|
|||||||
#!/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: CrazyWolf13
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://docs.seerr.dev/
|
|
||||||
|
|
||||||
APP="Seerr"
|
|
||||||
var_tags="${var_tags:-media}"
|
|
||||||
var_cpu="${var_cpu:-4}"
|
|
||||||
var_ram="${var_ram:-4096}"
|
|
||||||
var_disk="${var_disk:-12}"
|
|
||||||
var_os="${var_os:-debian}"
|
|
||||||
var_version="${var_version:-13}"
|
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
|
||||||
|
|
||||||
header_info "$APP"
|
|
||||||
variables
|
|
||||||
color
|
|
||||||
catch_errors
|
|
||||||
|
|
||||||
function update_script() {
|
|
||||||
header_info
|
|
||||||
check_container_storage
|
|
||||||
check_container_resources
|
|
||||||
|
|
||||||
if [[ ! -d /opt/seerr && ! -d /opt/jellyseerr && ! -d /opt/overseerr ]]; then
|
|
||||||
msg_error "No ${APP} Installation Found!"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Start Migration from Jellyseerr
|
|
||||||
if [[ -f /etc/systemd/system/jellyseerr.service ]]; then
|
|
||||||
msg_info "Stopping Jellyseerr"
|
|
||||||
$STD systemctl stop jellyseerr || true
|
|
||||||
$STD systemctl disable jellyseerr || true
|
|
||||||
[ -f /etc/systemd/system/jellyseerr.service ] && rm -f /etc/systemd/system/jellyseerr.service
|
|
||||||
msg_ok "Stopped Jellyseerr"
|
|
||||||
|
|
||||||
msg_info "Creating Backup (Patience)"
|
|
||||||
tar -czf /opt/jellyseerr_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /opt jellyseerr
|
|
||||||
msg_ok "Created Backup"
|
|
||||||
|
|
||||||
msg_info "Migrating Jellyseerr to seerr"
|
|
||||||
[ -d /opt/jellyseerr ] && mv /opt/jellyseerr /opt/seerr
|
|
||||||
[ -d /etc/jellyseerr ] && mv /etc/jellyseerr /etc/seerr
|
|
||||||
[ -f /etc/seerr/jellyseerr.conf ] && mv /etc/seerr/jellyseerr.conf /etc/seerr/seerr.conf
|
|
||||||
cat <<EOF >/etc/systemd/system/seerr.service
|
|
||||||
[Unit]
|
|
||||||
Description=Seerr Service
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
EnvironmentFile=/etc/seerr/seerr.conf
|
|
||||||
Environment=NODE_ENV=production
|
|
||||||
Type=exec
|
|
||||||
Restart=on-failure
|
|
||||||
WorkingDirectory=/opt/seerr
|
|
||||||
ExecStart=/usr/bin/node dist/index.js
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable -q --now seerr
|
|
||||||
msg_ok "Migrated Jellyserr to Seerr"
|
|
||||||
fi
|
|
||||||
# END Jellyseerr Migration
|
|
||||||
|
|
||||||
# Start Migration from Overseerr
|
|
||||||
if [[ -f /etc/systemd/system/overseerr.service ]]; then
|
|
||||||
msg_info "Stopping Overseerr"
|
|
||||||
$STD systemctl stop overseerr || true
|
|
||||||
$STD systemctl disable overseerr || true
|
|
||||||
[ -f /etc/systemd/system/overseerr.service ] && rm -f /etc/systemd/system/overseerr.service
|
|
||||||
msg_ok "Stopped Overseerr"
|
|
||||||
|
|
||||||
msg_info "Creating Backup (Patience)"
|
|
||||||
tar -czf /opt/overseerr_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /opt overseerr
|
|
||||||
msg_ok "Created Backup"
|
|
||||||
|
|
||||||
msg_info "Migrating Overseerr to seerr"
|
|
||||||
[ -d /opt/overseerr ] && mv /opt/overseerr /opt/seerr
|
|
||||||
mkdir -p /etc/seerr
|
|
||||||
cat <<EOF >/etc/seerr/seerr.conf
|
|
||||||
## Seerr's default port is 5055, if you want to use both, change this.
|
|
||||||
## specify on which port to listen
|
|
||||||
PORT=5055
|
|
||||||
|
|
||||||
## specify on which interface to listen, by default seerr listens on all interfaces
|
|
||||||
#HOST=127.0.0.1
|
|
||||||
|
|
||||||
## Uncomment if you want to force Node.js to resolve IPv4 before IPv6 (advanced users only)
|
|
||||||
# FORCE_IPV4_FIRST=true
|
|
||||||
EOF
|
|
||||||
cat <<EOF >/etc/systemd/system/seerr.service
|
|
||||||
[Unit]
|
|
||||||
Description=Seerr Service
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
EnvironmentFile=/etc/seerr/seerr.conf
|
|
||||||
Environment=NODE_ENV=production
|
|
||||||
Type=exec
|
|
||||||
Restart=on-failure
|
|
||||||
WorkingDirectory=/opt/seerr
|
|
||||||
ExecStart=/usr/bin/node dist/index.js
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable -q --now seerr
|
|
||||||
msg_ok "Migrated Overseerr to Seerr"
|
|
||||||
fi
|
|
||||||
# END Overseerr Migration
|
|
||||||
|
|
||||||
if check_for_gh_release "seerr" "seerr-team/seerr"; then
|
|
||||||
msg_info "Stopping Service"
|
|
||||||
systemctl stop seerr
|
|
||||||
msg_ok "Stopped Service"
|
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
|
||||||
cp -a /opt/seerr/config /opt/seerr_backup
|
|
||||||
msg_ok "Created Backup"
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "seerr" "seerr-team/seerr" "tarball"
|
|
||||||
|
|
||||||
msg_info "Updating PNPM Version"
|
|
||||||
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/seerr/package.json)
|
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
|
||||||
msg_ok "Updated PNPM Version"
|
|
||||||
|
|
||||||
msg_info "Updating Seerr"
|
|
||||||
cd /opt/seerr
|
|
||||||
rm -rf dist .next node_modules
|
|
||||||
export CYPRESS_INSTALL_BINARY=0
|
|
||||||
$STD pnpm install --frozen-lockfile
|
|
||||||
export NODE_OPTIONS="--max-old-space-size=3072"
|
|
||||||
$STD pnpm build
|
|
||||||
msg_ok "Updated Seerr"
|
|
||||||
|
|
||||||
msg_info "Restoring Backup"
|
|
||||||
rm -rf /opt/seerr/config
|
|
||||||
mv /opt/seerr_backup /opt/seerr/config
|
|
||||||
msg_ok "Restored Backup"
|
|
||||||
|
|
||||||
msg_info "Starting Service"
|
|
||||||
systemctl start seerr
|
|
||||||
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}:5055${CL}"
|
|
||||||
@@ -83,7 +83,6 @@ function update_script() {
|
|||||||
msg_ok "Started Soularr Timer"
|
msg_ok "Started Soularr Timer"
|
||||||
msg_ok "Updated Soularr successfully!"
|
msg_ok "Updated Soularr successfully!"
|
||||||
fi
|
fi
|
||||||
exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
start
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Updating VaultWarden to $VAULT (Patience)"
|
msg_info "Updating VaultWarden to $VAULT (Patience)"
|
||||||
cd /tmp/vaultwarden-src
|
cd /tmp/vaultwarden-src
|
||||||
VW_VERSION="$VAULT"
|
|
||||||
export VW_VERSION
|
|
||||||
$STD cargo build --features "sqlite,mysql,postgresql" --release
|
$STD cargo build --features "sqlite,mysql,postgresql" --release
|
||||||
if [[ -f /usr/bin/vaultwarden ]]; then
|
if [[ -f /usr/bin/vaultwarden ]]; then
|
||||||
cp target/release/vaultwarden /usr/bin/
|
cp target/release/vaultwarden /usr/bin/
|
||||||
|
|||||||
15
ct/zabbix.sh
15
ct/zabbix.sh
@@ -35,18 +35,15 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if systemctl cat zabbix-agent2.service &>/dev/null; then
|
if systemctl list-unit-files | grep -q zabbix-agent2.service; then
|
||||||
AGENT_SERVICE="zabbix-agent2"
|
AGENT_SERVICE="zabbix-agent2"
|
||||||
elif systemctl cat zabbix-agent.service &>/dev/null; then
|
|
||||||
AGENT_SERVICE="zabbix-agent"
|
|
||||||
else
|
else
|
||||||
AGENT_SERVICE=""
|
AGENT_SERVICE="zabbix-agent"
|
||||||
msg_warn "No Zabbix Agent service found, skipping agent actions"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_info "Stopping Services"
|
msg_info "Stopping Services"
|
||||||
systemctl stop zabbix-server
|
systemctl stop zabbix-server
|
||||||
[[ -n "$AGENT_SERVICE" ]] && systemctl stop "$AGENT_SERVICE"
|
systemctl stop "$AGENT_SERVICE"
|
||||||
msg_ok "Stopped Services"
|
msg_ok "Stopped Services"
|
||||||
|
|
||||||
read -rp "Choose Zabbix version [1] 7.0 LTS [2] 7.4 (Latest Stable) [3] Latest available (default: 2): " ZABBIX_CHOICE
|
read -rp "Choose Zabbix version [1] 7.0 LTS [2] 7.4 (Latest Stable) [3] Latest available (default: 2): " ZABBIX_CHOICE
|
||||||
@@ -86,13 +83,13 @@ function update_script() {
|
|||||||
|
|
||||||
$STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql
|
$STD apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php php8.4-pgsql
|
||||||
|
|
||||||
if [[ "$AGENT_SERVICE" == "zabbix-agent2" ]]; then
|
if [ "$AGENT_SERVICE" = "zabbix-agent2" ]; then
|
||||||
$STD apt install --only-upgrade zabbix-agent2 zabbix-agent2-plugin-postgresql
|
$STD apt install --only-upgrade zabbix-agent2 zabbix-agent2-plugin-postgresql
|
||||||
if [ -f /etc/zabbix/zabbix_agent2.d/plugins.d/nvidia.conf ]; then
|
if [ -f /etc/zabbix/zabbix_agent2.d/plugins.d/nvidia.conf ]; then
|
||||||
sed -i 's|^Plugins.NVIDIA.System.Path=.*|# Plugins.NVIDIA.System.Path=/usr/libexec/zabbix/zabbix-agent2-plugin-nvidia-gpu|' \
|
sed -i 's|^Plugins.NVIDIA.System.Path=.*|# Plugins.NVIDIA.System.Path=/usr/libexec/zabbix/zabbix-agent2-plugin-nvidia-gpu|' \
|
||||||
/etc/zabbix/zabbix_agent2.d/plugins.d/nvidia.conf
|
/etc/zabbix/zabbix_agent2.d/plugins.d/nvidia.conf
|
||||||
fi
|
fi
|
||||||
elif [[ "$AGENT_SERVICE" == "zabbix-agent" ]]; then
|
else
|
||||||
$STD apt install --only-upgrade zabbix-agent
|
$STD apt install --only-upgrade zabbix-agent
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -108,7 +105,7 @@ function update_script() {
|
|||||||
|
|
||||||
msg_info "Starting Services"
|
msg_info "Starting Services"
|
||||||
systemctl start zabbix-server
|
systemctl start zabbix-server
|
||||||
[[ -n "$AGENT_SERVICE" ]] && systemctl start "$AGENT_SERVICE"
|
systemctl start "$AGENT_SERVICE"
|
||||||
systemctl restart apache2
|
systemctl restart apache2
|
||||||
msg_ok "Started Services"
|
msg_ok "Started Services"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ebusd",
|
|
||||||
"slug": "ebusd",
|
|
||||||
"categories": [
|
|
||||||
16
|
|
||||||
],
|
|
||||||
"date_created": "2026-02-15",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": null,
|
|
||||||
"documentation": "https://github.com/john30/ebusd/wiki",
|
|
||||||
"website": "https://github.com/john30/ebusd",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/ebusd.webp",
|
|
||||||
"config_path": "/etc/default/ebusd",
|
|
||||||
"description": "ebusd is a daemon for handling communication with eBUS devices connected to a 2-wire `energy bus` used by numerous heating systems.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/ebusd.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 1,
|
|
||||||
"ram": 512,
|
|
||||||
"hdd": 2,
|
|
||||||
"os": "debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": "root",
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "For required post installation actions, checkout: `https://github.com/community-scripts/ProxmoxVE/discussions/11352`",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generated": "2026-02-16T12:14:16Z",
|
"generated": "2026-02-14T18:07:29Z",
|
||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"slug": "2fauth",
|
"slug": "2fauth",
|
||||||
@@ -193,16 +193,16 @@
|
|||||||
{
|
{
|
||||||
"slug": "cleanuparr",
|
"slug": "cleanuparr",
|
||||||
"repo": "Cleanuparr/Cleanuparr",
|
"repo": "Cleanuparr/Cleanuparr",
|
||||||
"version": "v2.6.2",
|
"version": "v2.6.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T02:15:19Z"
|
"date": "2026-02-13T10:00:19Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "cloudreve",
|
"slug": "cloudreve",
|
||||||
"repo": "cloudreve/cloudreve",
|
"repo": "cloudreve/cloudreve",
|
||||||
"version": "4.14.1",
|
"version": "4.14.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T01:39:24Z"
|
"date": "2026-02-14T06:05:06Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "comfyui",
|
"slug": "comfyui",
|
||||||
@@ -256,9 +256,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "dawarich",
|
"slug": "dawarich",
|
||||||
"repo": "Freika/dawarich",
|
"repo": "Freika/dawarich",
|
||||||
"version": "1.2.0",
|
"version": "1.1.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T22:33:56Z"
|
"date": "2026-02-08T14:42:45Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "discopanel",
|
"slug": "discopanel",
|
||||||
@@ -298,9 +298,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "donetick",
|
"slug": "donetick",
|
||||||
"repo": "donetick/donetick",
|
"repo": "donetick/donetick",
|
||||||
"version": "v0.1.74",
|
"version": "v0.1.73",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-14T23:21:45Z"
|
"date": "2026-02-12T23:42:30Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "drawio",
|
"slug": "drawio",
|
||||||
@@ -316,13 +316,6 @@
|
|||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-01-06T12:05:40Z"
|
"date": "2026-01-06T12:05:40Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"slug": "ebusd",
|
|
||||||
"repo": "john30/ebusd",
|
|
||||||
"version": "26.1",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2026-02-09T06:09:24Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"slug": "elementsynapse",
|
"slug": "elementsynapse",
|
||||||
"repo": "etkecc/synapse-admin",
|
"repo": "etkecc/synapse-admin",
|
||||||
@@ -361,9 +354,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "firefly",
|
"slug": "firefly",
|
||||||
"repo": "firefly-iii/firefly-iii",
|
"repo": "firefly-iii/firefly-iii",
|
||||||
"version": "v6.4.22",
|
"version": "v6.4.20",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T18:43:08Z"
|
"date": "2026-02-14T12:39:02Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "fladder",
|
"slug": "fladder",
|
||||||
@@ -410,9 +403,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "ghostfolio",
|
"slug": "ghostfolio",
|
||||||
"repo": "ghostfolio/ghostfolio",
|
"repo": "ghostfolio/ghostfolio",
|
||||||
"version": "2.239.0",
|
"version": "2.238.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T09:51:16Z"
|
"date": "2026-02-12T18:28:55Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "gitea",
|
"slug": "gitea",
|
||||||
@@ -557,9 +550,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "immich-public-proxy",
|
"slug": "immich-public-proxy",
|
||||||
"repo": "alangrainger/immich-public-proxy",
|
"repo": "alangrainger/immich-public-proxy",
|
||||||
"version": "v1.15.2",
|
"version": "v1.15.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T08:54:59Z"
|
"date": "2026-01-26T08:04:27Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "inspircd",
|
"slug": "inspircd",
|
||||||
@@ -578,16 +571,16 @@
|
|||||||
{
|
{
|
||||||
"slug": "invoiceninja",
|
"slug": "invoiceninja",
|
||||||
"repo": "invoiceninja/invoiceninja",
|
"repo": "invoiceninja/invoiceninja",
|
||||||
"version": "v5.12.60",
|
"version": "v5.12.59",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T00:11:31Z"
|
"date": "2026-02-13T02:26:13Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "jackett",
|
"slug": "jackett",
|
||||||
"repo": "Jackett/Jackett",
|
"repo": "Jackett/Jackett",
|
||||||
"version": "v0.24.1127",
|
"version": "v0.24.1113",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T08:43:41Z"
|
"date": "2026-02-14T17:46:58Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "jellystat",
|
"slug": "jellystat",
|
||||||
@@ -641,9 +634,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "kimai",
|
"slug": "kimai",
|
||||||
"repo": "kimai/kimai",
|
"repo": "kimai/kimai",
|
||||||
"version": "2.49.0",
|
"version": "2.48.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T20:40:19Z"
|
"date": "2026-01-31T18:10:59Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "kitchenowl",
|
"slug": "kitchenowl",
|
||||||
@@ -729,13 +722,6 @@
|
|||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2025-11-16T22:40:18Z"
|
"date": "2025-11-16T22:40:18Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"slug": "linkding",
|
|
||||||
"repo": "sissbruecker/linkding",
|
|
||||||
"version": "v1.45.0",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2026-01-06T20:31:04Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"slug": "linkstack",
|
"slug": "linkstack",
|
||||||
"repo": "linkstackorg/linkstack",
|
"repo": "linkstackorg/linkstack",
|
||||||
@@ -900,9 +886,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "nginx-ui",
|
"slug": "nginx-ui",
|
||||||
"repo": "0xJacky/nginx-ui",
|
"repo": "0xJacky/nginx-ui",
|
||||||
"version": "v2.3.3",
|
"version": "v2.3.2",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T00:58:14Z"
|
"date": "2025-12-09T09:47:15Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "nightscout",
|
"slug": "nightscout",
|
||||||
@@ -970,16 +956,23 @@
|
|||||||
{
|
{
|
||||||
"slug": "ots",
|
"slug": "ots",
|
||||||
"repo": "Luzifer/ots",
|
"repo": "Luzifer/ots",
|
||||||
"version": "v1.21.1",
|
"version": "v1.21.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T12:12:23Z"
|
"date": "2026-01-19T23:21:29Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "outline",
|
"slug": "outline",
|
||||||
"repo": "outline/outline",
|
"repo": "outline/outline",
|
||||||
"version": "v1.5.0",
|
"version": "v1.4.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T18:04:16Z"
|
"date": "2026-01-27T23:43:03Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"slug": "overseerr",
|
||||||
|
"repo": "sct/overseerr",
|
||||||
|
"version": "v1.34.0",
|
||||||
|
"pinned": false,
|
||||||
|
"date": "2025-03-26T08:48:34Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "owncast",
|
"slug": "owncast",
|
||||||
@@ -1019,9 +1012,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "paperless-gpt",
|
"slug": "paperless-gpt",
|
||||||
"repo": "icereed/paperless-gpt",
|
"repo": "icereed/paperless-gpt",
|
||||||
"version": "v0.25.0",
|
"version": "v0.24.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T08:31:48Z"
|
"date": "2026-01-14T21:28:09Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "paperless-ngx",
|
"slug": "paperless-ngx",
|
||||||
@@ -1061,9 +1054,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "pelican-wings",
|
"slug": "pelican-wings",
|
||||||
"repo": "pelican-dev/wings",
|
"repo": "pelican-dev/wings",
|
||||||
"version": "v1.0.0-beta24",
|
"version": "v1.0.0-beta23",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T16:09:56Z"
|
"date": "2026-02-09T22:10:26Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "pf2etools",
|
"slug": "pf2etools",
|
||||||
@@ -1275,13 +1268,6 @@
|
|||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2025-03-28T13:00:23Z"
|
"date": "2025-03-28T13:00:23Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"slug": "romm",
|
|
||||||
"repo": "RetroAchievements/RALibretro",
|
|
||||||
"version": "1.8.2",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2026-01-23T17:03:31Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"slug": "rustdeskserver",
|
"slug": "rustdeskserver",
|
||||||
"repo": "rustdesk/rustdesk-server",
|
"repo": "rustdesk/rustdesk-server",
|
||||||
@@ -1324,19 +1310,12 @@
|
|||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2025-03-08T10:49:04Z"
|
"date": "2025-03-08T10:49:04Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"slug": "seerr",
|
|
||||||
"repo": "seerr-team/seerr",
|
|
||||||
"version": "v3.0.1",
|
|
||||||
"pinned": false,
|
|
||||||
"date": "2026-02-14T19:30:24Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"slug": "semaphore",
|
"slug": "semaphore",
|
||||||
"repo": "semaphoreui/semaphore",
|
"repo": "semaphoreui/semaphore",
|
||||||
"version": "v2.17.2",
|
"version": "v2.17.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T10:27:40Z"
|
"date": "2026-02-13T21:08:30Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "shelfmark",
|
"slug": "shelfmark",
|
||||||
@@ -1446,9 +1425,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "tautulli",
|
"slug": "tautulli",
|
||||||
"repo": "Tautulli/Tautulli",
|
"repo": "Tautulli/Tautulli",
|
||||||
"version": "v2.16.1",
|
"version": "v2.16.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T20:40:37Z"
|
"date": "2025-09-09T01:05:45Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "teddycloud",
|
"slug": "teddycloud",
|
||||||
@@ -1502,9 +1481,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "tracearr",
|
"slug": "tracearr",
|
||||||
"repo": "connorgallopo/Tracearr",
|
"repo": "connorgallopo/Tracearr",
|
||||||
"version": "v1.4.18",
|
"version": "v1.4.17",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T19:55:40Z"
|
"date": "2026-02-11T01:33:21Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "tracktor",
|
"slug": "tracktor",
|
||||||
@@ -1719,9 +1698,9 @@
|
|||||||
{
|
{
|
||||||
"slug": "yubal",
|
"slug": "yubal",
|
||||||
"repo": "guillevc/yubal",
|
"repo": "guillevc/yubal",
|
||||||
"version": "v0.6.0",
|
"version": "v0.5.0",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T17:47:56Z"
|
"date": "2026-02-09T22:11:32Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "zigbee2mqtt",
|
"slug": "zigbee2mqtt",
|
||||||
@@ -1740,16 +1719,16 @@
|
|||||||
{
|
{
|
||||||
"slug": "zitadel",
|
"slug": "zitadel",
|
||||||
"repo": "zitadel/zitadel",
|
"repo": "zitadel/zitadel",
|
||||||
"version": "v4.11.0",
|
"version": "v4.10.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-16T09:48:38Z"
|
"date": "2026-01-30T06:52:53Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "zoraxy",
|
"slug": "zoraxy",
|
||||||
"repo": "tobychui/zoraxy",
|
"repo": "tobychui/zoraxy",
|
||||||
"version": "v3.3.2-rc1",
|
"version": "v3.3.1",
|
||||||
"pinned": false,
|
"pinned": false,
|
||||||
"date": "2026-02-15T02:16:17Z"
|
"date": "2026-01-28T13:52:02Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "zwave-js-ui",
|
"slug": "zwave-js-ui",
|
||||||
|
|||||||
35
frontend/public/json/jellyseerr.json
Normal file
35
frontend/public/json/jellyseerr.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Jellyseerr",
|
||||||
|
"slug": "jellyseerr",
|
||||||
|
"categories": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"date_created": "2024-05-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 5055,
|
||||||
|
"documentation": "https://docs.jellyseerr.dev/",
|
||||||
|
"website": "https://github.com/Fallenbagel/jellyseerr",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/jellyseerr.webp",
|
||||||
|
"config_path": "/etc/jellyseerr/jellyseerr.conf",
|
||||||
|
"description": "Jellyseerr is a free and open source software application for managing requests for your media library. It is a a fork of Overseerr built to bring support for Jellyfin & Emby media servers.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/jellyseerr.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 4,
|
||||||
|
"ram": 4096,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "debian",
|
||||||
|
"version": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "linkding",
|
|
||||||
"slug": "linkding",
|
|
||||||
"categories": [
|
|
||||||
12
|
|
||||||
],
|
|
||||||
"date_created": "2026-02-16",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 9090,
|
|
||||||
"documentation": "https://linkding.link/",
|
|
||||||
"website": "https://linkding.link/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/linkding.webp",
|
|
||||||
"config_path": "/opt/linkding/.env",
|
|
||||||
"description": "linkding is a self-hosted bookmark manager that is designed to be minimal, fast, and easy to set up. It features a clean UI, tag-based organization, bulk editing, Markdown notes, read it later functionality, sharing, REST API, and browser extensions for Firefox and Chrome.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/linkding.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 1024,
|
|
||||||
"hdd": 4,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": "admin",
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": [
|
|
||||||
{
|
|
||||||
"text": "Admin credentials are stored in /opt/linkding/.env",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"notes": [
|
"notes": [
|
||||||
{
|
{
|
||||||
"text": "Valid TLS certificates and fully-qualified domain names behind a reverse proxy (Caddy) for 3 services - OpenCloud (port: 9200), Collabora (port: 9980), and WOPI (port: 9300) are **REQUIRED**",
|
"text": "Valid TLS certificates and fully-qualified domain names behind a reverse proxy (Caddy) for 3 services - OpenCloud, Collabora, and WOPI are **REQUIRED**",
|
||||||
"type": "warning"
|
"type": "warning"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
35
frontend/public/json/overseerr.json
Normal file
35
frontend/public/json/overseerr.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "Overseerr",
|
||||||
|
"slug": "overseerr",
|
||||||
|
"categories": [
|
||||||
|
14
|
||||||
|
],
|
||||||
|
"date_created": "2024-05-02",
|
||||||
|
"type": "ct",
|
||||||
|
"updateable": true,
|
||||||
|
"privileged": false,
|
||||||
|
"interface_port": 5055,
|
||||||
|
"documentation": "https://docs.overseerr.dev/",
|
||||||
|
"website": "https://overseerr.dev/",
|
||||||
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/overseerr.webp",
|
||||||
|
"config_path": "/opt/overseerr/config/settings.json",
|
||||||
|
"description": "Overseerr is a request management and media discovery tool built to work with your existing Plex ecosystem.",
|
||||||
|
"install_methods": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"script": "ct/overseerr.sh",
|
||||||
|
"resources": {
|
||||||
|
"cpu": 2,
|
||||||
|
"ram": 4096,
|
||||||
|
"hdd": 8,
|
||||||
|
"os": "debian",
|
||||||
|
"version": "13"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default_credentials": {
|
||||||
|
"username": null,
|
||||||
|
"password": null
|
||||||
|
},
|
||||||
|
"notes": []
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 3000,
|
"interface_port": 3399,
|
||||||
"documentation": "https://docs.patchmon.net",
|
"documentation": "https://docs.patchmon.net",
|
||||||
"website": "https://patchmon.net",
|
"website": "https://patchmon.net",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/patchmon.webp",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/patchmon.webp",
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "RomM",
|
|
||||||
"slug": "romm",
|
|
||||||
"categories": [
|
|
||||||
24
|
|
||||||
],
|
|
||||||
"date_created": "2026-02-16",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 80,
|
|
||||||
"documentation": "https://docs.romm.app/latest/",
|
|
||||||
"website": "https://romm.app/",
|
|
||||||
"config_path": "/opt/romm/.env",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/romm.webp",
|
|
||||||
"description": "RomM (ROM Manager) allows you to scan, enrich, browse and play your game collection with a clean and responsive interface. Support for multiple platforms, various naming schemes, and custom tags.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/romm.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 2,
|
|
||||||
"ram": 4096,
|
|
||||||
"hdd": 20,
|
|
||||||
"os": "debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Seerr",
|
|
||||||
"slug": "seerr",
|
|
||||||
"categories": [
|
|
||||||
13
|
|
||||||
],
|
|
||||||
"date_created": "2026-02-15",
|
|
||||||
"type": "ct",
|
|
||||||
"updateable": true,
|
|
||||||
"privileged": false,
|
|
||||||
"interface_port": 5055,
|
|
||||||
"documentation": "https://docs.seerr.dev/",
|
|
||||||
"website": "https://seerr.dev/",
|
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/seerr.webp",
|
|
||||||
"config_path": "/etc/seerr/seerr.conf",
|
|
||||||
"description": "Open-source media request and discovery manager for Jellyfin, Plex, and Emby. Unified version of Overseerr and Jellyseerr.",
|
|
||||||
"install_methods": [
|
|
||||||
{
|
|
||||||
"type": "default",
|
|
||||||
"script": "ct/seerr.sh",
|
|
||||||
"resources": {
|
|
||||||
"cpu": 4,
|
|
||||||
"ram": 4096,
|
|
||||||
"hdd": 12,
|
|
||||||
"os": "Debian",
|
|
||||||
"version": "13"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default_credentials": {
|
|
||||||
"username": null,
|
|
||||||
"password": null
|
|
||||||
},
|
|
||||||
"notes": []
|
|
||||||
}
|
|
||||||
@@ -1,40 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "Wishlist",
|
"name": "Wishlist",
|
||||||
"slug": "wishlist",
|
"slug": "wishlist",
|
||||||
"categories": [
|
"categories": [
|
||||||
12
|
12
|
||||||
],
|
],
|
||||||
"date_created": "2026-02-04",
|
"date_created": "2026-02-04",
|
||||||
"type": "ct",
|
"type": "ct",
|
||||||
"updateable": true,
|
"updateable": true,
|
||||||
"privileged": false,
|
"privileged": false,
|
||||||
"interface_port": 3280,
|
"interface_port": 3280,
|
||||||
"documentation": "https://github.com/cmintey/wishlist/blob/main/README.md#getting-started",
|
"documentation": "https://github.com/cmintey/wishlist/blob/main/README.md#getting-started",
|
||||||
"website": "https://github.com/cmintey/wishlist",
|
"config_path": "/opt/wishlist/.env",
|
||||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cmintey-wishlist.webp",
|
"website": "https://github.com/cmintey/wishlist",
|
||||||
"config_path": "/opt/wishlist/.env",
|
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/cmintey-wishlist.webp",
|
||||||
"description": "Wishlist is a self-hosted wishlist application that you can share with your friends and family. You no longer have to wonder what to get your family for the holidays, simply check their wishlist and claim any available item!",
|
"description": "Wishlist is a self-hosted wishlist application that you can share with your friends and family. You no longer have to wonder what to get your family for the holidays, simply check their wishlist and claim any available item!",
|
||||||
"install_methods": [
|
"install_methods": [
|
||||||
{
|
{
|
||||||
"type": "default",
|
"type": "default",
|
||||||
"script": "ct/wishlist.sh",
|
"script": "ct/wishlist.sh",
|
||||||
"resources": {
|
"resources": {
|
||||||
"cpu": 2,
|
"cpu": 2,
|
||||||
"ram": 2048,
|
"ram": 2048,
|
||||||
"hdd": 5,
|
"hdd": 5,
|
||||||
"os": "Debian",
|
"os": "Debian",
|
||||||
"version": "13"
|
"version": "13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default_credentials": {
|
"default_credentials": {
|
||||||
"username": null,
|
"username": null,
|
||||||
"password": null
|
"password": null
|
||||||
},
|
},
|
||||||
"notes": [
|
"notes": []
|
||||||
{
|
|
||||||
"text": "When using a reverse proxy with this script, please edit the`ORIGIN` value in `/opt/wishlist/.env` to point to your new URL, otherwise creating an admin account or logging in will not work.",
|
|
||||||
"type": "info"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ $STD apk add --no-cache \
|
|||||||
libc6-compat
|
libc6-compat
|
||||||
msg_ok "Installed dependencies"
|
msg_ok "Installed dependencies"
|
||||||
|
|
||||||
RELEASE=$(curl -fsSL https://teamspeak.com/en/downloads/#server | sed -n 's/.*teamspeak3-server_linux_amd64-\([0-9.]*[0-9]\).*/\1/p' | awk 'NR==1')
|
RELEASE=$(curl -fsSL https://teamspeak.com/en/downloads/#server | sed -n 's/.*teamspeak3-server_linux_amd64-\([0-9.]*[0-9]\).*/\1/p' | head -1)
|
||||||
msg_info "Installing Teamspeak Server v${RELEASE}"
|
msg_info "Installing Teamspeak Server v${RELEASE}"
|
||||||
mkdir -p /opt/teamspeak-server
|
mkdir -p /opt/teamspeak-server
|
||||||
cd /opt/teamspeak-server
|
cd /opt/teamspeak-server
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ msg_info "Setup CryptPad"
|
|||||||
cd /opt/cryptpad
|
cd /opt/cryptpad
|
||||||
$STD npm ci
|
$STD npm ci
|
||||||
$STD npm run install:components
|
$STD npm run install:components
|
||||||
if [[ "$onlyoffice" =~ ^[Yy]$ ]]; then
|
$STD npm run build
|
||||||
$STD bash -c "./install-onlyoffice.sh --accept-license"
|
|
||||||
fi
|
|
||||||
cp config/config.example.js config/config.js
|
cp config/config.example.js config/config.js
|
||||||
sed -i "51s/localhost/${LOCAL_IP}/g" /opt/cryptpad/config/config.js
|
sed -i "51s/localhost/${LOCAL_IP}/g" /opt/cryptpad/config/config.js
|
||||||
sed -i "80s#//httpAddress: 'localhost'#httpAddress: '0.0.0.0'#g" /opt/cryptpad/config/config.js
|
sed -i "80s#//httpAddress: 'localhost'#httpAddress: '0.0.0.0'#g" /opt/cryptpad/config/config.js
|
||||||
$STD npm run build
|
if [[ "$onlyoffice" =~ ^[Yy]$ ]]; then
|
||||||
|
$STD bash -c "./install-onlyoffice.sh --accept-license"
|
||||||
|
fi
|
||||||
msg_ok "Setup CryptPad"
|
msg_ok "Setup CryptPad"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: Joerg Heinemann (heinemannj)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://github.com/john30/ebusd
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing ebusd"
|
|
||||||
fetch_and_deploy_gh_release "ebusd" "john30/ebusd" "binary" "latest" "" "ebusd-*_amd64-trixie_mqtt1.deb"
|
|
||||||
systemctl enable -q ebusd
|
|
||||||
msg_ok "Installed ebusd"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
64
install/jellyseerr-install.sh
Normal file
64
install/jellyseerr-install.sh
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://docs.jellyseerr.dev/
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
msg_info "Installing Dependencies"
|
||||||
|
$STD apt-get install -y \
|
||||||
|
git \
|
||||||
|
build-essential
|
||||||
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
git clone -q https://github.com/Fallenbagel/jellyseerr.git /opt/jellyseerr
|
||||||
|
cd /opt/jellyseerr
|
||||||
|
$STD git checkout main
|
||||||
|
|
||||||
|
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/jellyseerr/package.json)
|
||||||
|
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
||||||
|
|
||||||
|
msg_info "Installing Jellyseerr (Patience)"
|
||||||
|
export CYPRESS_INSTALL_BINARY=0
|
||||||
|
cd /opt/jellyseerr
|
||||||
|
$STD pnpm install --frozen-lockfile
|
||||||
|
export NODE_OPTIONS="--max-old-space-size=3072"
|
||||||
|
$STD pnpm build
|
||||||
|
mkdir -p /etc/jellyseerr/
|
||||||
|
cat <<EOF >/etc/jellyseerr/jellyseerr.conf
|
||||||
|
PORT=5055
|
||||||
|
# HOST=0.0.0.0
|
||||||
|
# JELLYFIN_TYPE=emby
|
||||||
|
EOF
|
||||||
|
msg_ok "Installed Jellyseerr"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/jellyseerr.service
|
||||||
|
[Unit]
|
||||||
|
Description=jellyseerr Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=/etc/jellyseerr/jellyseerr.conf
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
Type=exec
|
||||||
|
WorkingDirectory=/opt/jellyseerr
|
||||||
|
ExecStart=/usr/bin/node dist/index.js
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now jellyseerr
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: MickLesk (MickLesk)
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://linkding.link/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
$STD apt install -y \
|
|
||||||
build-essential \
|
|
||||||
pkg-config \
|
|
||||||
python3-dev \
|
|
||||||
nginx \
|
|
||||||
libpq-dev \
|
|
||||||
libicu-dev \
|
|
||||||
libsqlite3-dev \
|
|
||||||
libffi-dev
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
|
||||||
setup_uv
|
|
||||||
fetch_and_deploy_gh_release "linkding" "sissbruecker/linkding"
|
|
||||||
|
|
||||||
msg_info "Building Frontend"
|
|
||||||
cd /opt/linkding
|
|
||||||
$STD npm ci
|
|
||||||
$STD npm run build
|
|
||||||
ln -sf /usr/lib/x86_64-linux-gnu/mod_icu.so /opt/linkding/libicu.so
|
|
||||||
msg_ok "Built Frontend"
|
|
||||||
|
|
||||||
msg_info "Setting up LinkDing"
|
|
||||||
rm -f bookmarks/settings/dev.py
|
|
||||||
touch bookmarks/settings/custom.py
|
|
||||||
$STD uv sync --no-dev --frozen
|
|
||||||
$STD uv pip install gunicorn
|
|
||||||
mkdir -p data/{favicons,previews,assets}
|
|
||||||
ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
|
|
||||||
cat <<EOF >/opt/linkding/.env
|
|
||||||
LD_SUPERUSER_NAME=admin
|
|
||||||
LD_SUPERUSER_PASSWORD=${ADMIN_PASS}
|
|
||||||
LD_CSRF_TRUSTED_ORIGINS=http://${LOCAL_IP}:9090
|
|
||||||
EOF
|
|
||||||
set -a && source /opt/linkding/.env && set +a
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py generate_secret_key
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py migrate
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py enable_wal
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py create_initial_superuser
|
|
||||||
$STD /opt/linkding/.venv/bin/python manage.py collectstatic --no-input
|
|
||||||
msg_ok "Set up LinkDing"
|
|
||||||
|
|
||||||
msg_info "Creating Services"
|
|
||||||
cat <<EOF >/etc/systemd/system/linkding.service
|
|
||||||
[Unit]
|
|
||||||
Description=linkding Bookmark Manager
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/linkding
|
|
||||||
EnvironmentFile=/opt/linkding/.env
|
|
||||||
ExecStart=/opt/linkding/.venv/bin/gunicorn \
|
|
||||||
--bind 127.0.0.1:8000 \
|
|
||||||
--workers 3 \
|
|
||||||
--threads 2 \
|
|
||||||
--timeout 120 \
|
|
||||||
bookmarks.wsgi:application
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
cat <<EOF >/etc/systemd/system/linkding-tasks.service
|
|
||||||
[Unit]
|
|
||||||
Description=linkding Background Tasks
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
User=root
|
|
||||||
WorkingDirectory=/opt/linkding
|
|
||||||
EnvironmentFile=/opt/linkding/.env
|
|
||||||
ExecStart=/opt/linkding/.venv/bin/python manage.py run_huey
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
cat <<'EOF' >/etc/nginx/sites-available/linkding
|
|
||||||
server {
|
|
||||||
listen 9090;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
client_max_body_size 20M;
|
|
||||||
|
|
||||||
location /static/ {
|
|
||||||
alias /opt/linkding/static/;
|
|
||||||
expires 30d;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://127.0.0.1:8000;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_redirect off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
$STD rm -f /etc/nginx/sites-enabled/default
|
|
||||||
$STD ln -sf /etc/nginx/sites-available/linkding /etc/nginx/sites-enabled/linkding
|
|
||||||
systemctl enable -q --now nginx linkding linkding-tasks
|
|
||||||
systemctl restart nginx
|
|
||||||
msg_ok "Created Services"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
44
install/overseerr-install.sh
Normal file
44
install/overseerr-install.sh
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright (c) 2021-2026 tteck
|
||||||
|
# Author: tteck (tteckster)
|
||||||
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
|
# Source: https://overseerr.dev/
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
|
color
|
||||||
|
verb_ip6
|
||||||
|
catch_errors
|
||||||
|
setting_up_container
|
||||||
|
network_check
|
||||||
|
update_os
|
||||||
|
|
||||||
|
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
|
||||||
|
fetch_and_deploy_gh_release "overseerr" "sct/overseerr" "tarball"
|
||||||
|
|
||||||
|
msg_info "Configuring Overseerr (Patience)"
|
||||||
|
cd /opt/overseerr
|
||||||
|
$STD yarn install
|
||||||
|
$STD yarn build
|
||||||
|
msg_ok "Configured Overseerr"
|
||||||
|
|
||||||
|
msg_info "Creating Service"
|
||||||
|
cat <<EOF >/etc/systemd/system/overseerr.service
|
||||||
|
[Unit]
|
||||||
|
Description=Overseerr Service
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=exec
|
||||||
|
WorkingDirectory=/opt/overseerr
|
||||||
|
ExecStart=/usr/bin/yarn start
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl enable -q --now overseerr
|
||||||
|
msg_ok "Created Service"
|
||||||
|
|
||||||
|
motd_ssh
|
||||||
|
customize
|
||||||
|
cleanup_lxc
|
||||||
@@ -27,42 +27,162 @@ PG_DB_NAME="patchmon_db" PG_DB_USER="patchmon_usr" setup_postgresql_db
|
|||||||
fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon"
|
fetch_and_deploy_gh_release "PatchMon" "PatchMon/PatchMon" "tarball" "latest" "/opt/patchmon"
|
||||||
|
|
||||||
msg_info "Configuring PatchMon"
|
msg_info "Configuring PatchMon"
|
||||||
VERSION=$(get_latest_github_release "PatchMon/PatchMon")
|
|
||||||
export NODE_ENV=production
|
|
||||||
cd /opt/patchmon
|
cd /opt/patchmon
|
||||||
|
export NODE_ENV=production
|
||||||
|
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
||||||
|
cd /opt/patchmon/backend
|
||||||
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
$STD npm install --no-audit --no-fund --no-save --ignore-scripts
|
||||||
|
|
||||||
cd /opt/patchmon/frontend
|
cd /opt/patchmon/frontend
|
||||||
cat <<EOF >./.env
|
$STD npm install --include=dev --no-audit --no-fund --no-save --ignore-scripts
|
||||||
VITE_API_URL=http://${LOCAL_IP}:3001/api/v1
|
|
||||||
VITE_APP_NAME=PatchMon
|
|
||||||
VITE_APP_VERSION=${VERSION}
|
|
||||||
EOF
|
|
||||||
$STD npm install --no-audit --no-fund --no-save --ignore-scripts --include=dev
|
|
||||||
$STD npm run build
|
$STD npm run build
|
||||||
|
JWT_SECRET="$(openssl rand -base64 64 | tr -d "=+/" | cut -c1-50)"
|
||||||
|
cat <<EOF >/opt/patchmon/backend/.env
|
||||||
|
# Database Configuration
|
||||||
|
DATABASE_URL="postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME"
|
||||||
|
PY_THRESHOLD=3M_DB_CONN_MAX_ATTEMPTS=30
|
||||||
|
PM_DB_CONN_WAIT_INTERVAL=2
|
||||||
|
|
||||||
JWT_SECRET="$(openssl rand -hex 64)"
|
# JWT Configuration
|
||||||
mv /opt/patchmon/backend/env.example /opt/patchmon/backend/.env
|
JWT_SECRET="$JWT_SECRET"
|
||||||
sed -i -e "s|DATABASE_URL=.*|DATABASE_URL=\"postgresql://$PG_DB_USER:$PG_DB_PASS@localhost:5432/$PG_DB_NAME\"|" \
|
JWT_EXPIRES_IN=1h
|
||||||
-e "/JWT_SECRET/s/[=$].*/=$JWT_SECRET/" \
|
JWT_REFRESH_EXPIRES_IN=7d
|
||||||
-e "\|CORS_ORIGIN|s|localhost|$LOCAL_IP|" \
|
|
||||||
-e "/PORT=3001/aSERVER_PROTOCOL=http \\
|
# Server Configuration
|
||||||
SERVER_HOST=$LOCAL_IP \\
|
PORT=3399
|
||||||
SERVER_PORT=3000" \
|
NODE_ENV=production
|
||||||
-e '/_ENV=production/aTRUST_PROXY=1' \
|
|
||||||
-e '/REDIS_USER=.*/,+1d' /opt/patchmon/backend/.env
|
# API Configuration
|
||||||
|
API_VERSION=v1
|
||||||
|
|
||||||
|
# CORS Configuration
|
||||||
|
CORS_ORIGIN="http://$LOCAL_IP"
|
||||||
|
|
||||||
|
# Session Configuration
|
||||||
|
SESSION_INACTIVITY_TIMEOUT_MINUTES=30
|
||||||
|
|
||||||
|
# User Configuration
|
||||||
|
DEFAULT_USER_ROLE=user
|
||||||
|
|
||||||
|
# Rate Limiting (times in milliseconds)
|
||||||
|
RATE_LIMIT_WINDOW_MS=900000
|
||||||
|
RATE_LIMIT_MAX=5000
|
||||||
|
AUTH_RATE_LIMIT_WINDOW_MS=600000
|
||||||
|
AUTH_RATE_LIMIT_MAX=500
|
||||||
|
AGENT_RATE_LIMIT_WINDOW_MS=60000
|
||||||
|
AGENT_RATE_LIMIT_MAX=1000
|
||||||
|
|
||||||
|
# Redis Configuration
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
LOG_LEVEL=info
|
||||||
|
ENABLE_LOGGING=true
|
||||||
|
|
||||||
|
# TFA Configuration
|
||||||
|
TFA_REMEMBER_ME_EXPIRES_IN=30d
|
||||||
|
TFA_MAX_REMEMBER_SESSIONS=5
|
||||||
|
TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF >/opt/patchmon/frontend/.env
|
||||||
|
VITE_API_URL=http://$LOCAL_IP/api/v1
|
||||||
|
VITE_APP_NAME=PatchMon
|
||||||
|
VITE_APP_VERSION=1.3.0
|
||||||
|
EOF
|
||||||
|
|
||||||
cd /opt/patchmon/backend
|
cd /opt/patchmon/backend
|
||||||
$STD npm run db:generate
|
|
||||||
$STD npx prisma migrate deploy
|
$STD npx prisma migrate deploy
|
||||||
|
$STD npx prisma generate
|
||||||
msg_ok "Configured PatchMon"
|
msg_ok "Configured PatchMon"
|
||||||
|
|
||||||
msg_info "Configuring Nginx"
|
msg_info "Configuring Nginx"
|
||||||
cp /opt/patchmon/docker/nginx.conf.template /etc/nginx/sites-available/patchmon.conf
|
cat <<EOF >/etc/nginx/sites-available/patchmon.conf
|
||||||
sed -i -e 's|proxy_pass .*|proxy_pass http://127.0.0.1:3001;|' \
|
map \$http_x_forwarded_proto \$proxy_corrected_scheme {
|
||||||
-e '\|try_files |i\ root /opt/patchmon/frontend/dist;' \
|
default \$scheme; # Fallback to Nginx's actual connection scheme if no X-Forwarded-Proto header was set
|
||||||
-e 's|alias.*|alias /opt/patchmon/frontend/dist/assets;|' \
|
https https; # If X-Forwarded-Proto is 'https', use 'https'
|
||||||
-e '\|expires 1y|i\ root /opt/patchmon/frontend/dist;' /etc/nginx/sites-available/patchmon.conf
|
http http; # If X-Forwarded-Proto is 'http', use 'http'
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
# Listen on both IPv4 and IPv6 (with all hostnames)
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options DENY always;
|
||||||
|
add_header X-Content-Type-Options nosniff always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
location / {
|
||||||
|
root /opt/patchmon/frontend/dist;
|
||||||
|
try_files \$uri \$uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bull Board proxy
|
||||||
|
location /bullboard {
|
||||||
|
proxy_pass http://127.0.0.1:3399;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$proxy_corrected_scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host \$host;
|
||||||
|
proxy_set_header Cookie \$http_cookie;
|
||||||
|
proxy_cache_bypass \$http_upgrade;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_connect_timeout 75s;
|
||||||
|
|
||||||
|
# Enable cookie passthrough
|
||||||
|
proxy_pass_header Set-Cookie;
|
||||||
|
proxy_cookie_path / /;
|
||||||
|
|
||||||
|
# Preserve original client IP
|
||||||
|
proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for;
|
||||||
|
if (\$request_method = 'OPTIONS') {
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# API proxy
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://127.0.0.1:3399;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$proxy_corrected_scheme;
|
||||||
|
proxy_cache_bypass \$http_upgrade;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_connect_timeout 75s;
|
||||||
|
|
||||||
|
# Preserve original client IP
|
||||||
|
proxy_set_header X-Original-Forwarded-For \$http_x_forwarded_for;
|
||||||
|
if (\$request_method = 'OPTIONS') {
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Static assets caching (exclude Bull Board assets)
|
||||||
|
location ~* ^/(?!bullboard).*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
root /opt/patchmon/frontend/dist;
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://127.0.0.1:3399/health;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/
|
ln -sf /etc/nginx/sites-available/patchmon.conf /etc/nginx/sites-enabled/
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
$STD nginx -t
|
$STD nginx -t
|
||||||
@@ -78,7 +198,7 @@ After=network.target postgresql.service
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/patchmon/backend
|
WorkingDirectory=/opt/patchmon/backend
|
||||||
ExecStart=/usr/bin/npm run start
|
ExecStart=/usr/bin/node src/server.js
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
Environment=NODE_ENV=production
|
Environment=NODE_ENV=production
|
||||||
@@ -95,6 +215,57 @@ EOF
|
|||||||
systemctl enable -q --now patchmon-server
|
systemctl enable -q --now patchmon-server
|
||||||
msg_ok "Created and started service"
|
msg_ok "Created and started service"
|
||||||
|
|
||||||
|
msg_info "Updating settings"
|
||||||
|
cat <<EOF >/opt/patchmon/backend/update-settings.js
|
||||||
|
const { PrismaClient } = require('@prisma/client');
|
||||||
|
const { v4: uuidv4 } = require('uuid');
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
async function updateSettings() {
|
||||||
|
try {
|
||||||
|
const existingSettings = await prisma.settings.findFirst();
|
||||||
|
|
||||||
|
const settingsData = {
|
||||||
|
id: uuidv4(),
|
||||||
|
server_url: 'http://$LOCAL_IP',
|
||||||
|
server_protocol: 'http',
|
||||||
|
server_host: '$LOCAL_IP',
|
||||||
|
server_port: 3399,
|
||||||
|
update_interval: 60,
|
||||||
|
auto_update: true,
|
||||||
|
signup_enabled: false,
|
||||||
|
ignore_ssl_self_signed: false,
|
||||||
|
updated_at: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existingSettings) {
|
||||||
|
// Update existing settings
|
||||||
|
await prisma.settings.update({
|
||||||
|
where: { id: existingSettings.id },
|
||||||
|
data: settingsData
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Create new settings record
|
||||||
|
await prisma.settings.create({
|
||||||
|
data: settingsData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Database settings updated successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error updating settings:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
} finally {
|
||||||
|
await prisma.\$disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSettings();
|
||||||
|
EOF
|
||||||
|
cd /opt/patchmon/backend
|
||||||
|
$STD node update-settings.js
|
||||||
|
msg_ok "Settings updated successfully"
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
cleanup_lxc
|
cleanup_lxc
|
||||||
|
|||||||
@@ -1,344 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: MickLesk (CanbiZ) | DevelopmentCats | AlphaLawless
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://romm.app
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
$STD apt install -y \
|
|
||||||
acl \
|
|
||||||
git \
|
|
||||||
build-essential \
|
|
||||||
libssl-dev \
|
|
||||||
libffi-dev \
|
|
||||||
libmagic-dev \
|
|
||||||
python3-dev \
|
|
||||||
python3-pip \
|
|
||||||
python3-venv \
|
|
||||||
libmariadb3 \
|
|
||||||
libmariadb-dev \
|
|
||||||
libpq-dev \
|
|
||||||
libbz2-dev \
|
|
||||||
libreadline-dev \
|
|
||||||
libsqlite3-dev \
|
|
||||||
zlib1g-dev \
|
|
||||||
liblzma-dev \
|
|
||||||
libncurses5-dev \
|
|
||||||
libncursesw5-dev \
|
|
||||||
redis-server \
|
|
||||||
redis-tools \
|
|
||||||
p7zip-full \
|
|
||||||
tzdata \
|
|
||||||
nginx
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
PYTHON_VERSION="3.13" setup_uv
|
|
||||||
NODE_VERSION="22" setup_nodejs
|
|
||||||
setup_mariadb
|
|
||||||
MARIADB_DB_NAME="romm" MARIADB_DB_USER="romm" setup_mariadb_db
|
|
||||||
|
|
||||||
msg_info "Creating directories"
|
|
||||||
mkdir -p /opt/romm \
|
|
||||||
/var/lib/romm/config \
|
|
||||||
/var/lib/romm/resources \
|
|
||||||
/var/lib/romm/assets/{saves,states,screenshots} \
|
|
||||||
/var/lib/romm/library/roms \
|
|
||||||
/var/lib/romm/library/bios
|
|
||||||
msg_ok "Created directories"
|
|
||||||
|
|
||||||
msg_info "Creating configuration file"
|
|
||||||
cat <<'EOF' >/var/lib/romm/config/config.yml
|
|
||||||
# RomM Configuration File
|
|
||||||
# Documentation: https://docs.romm.app/latest/Getting-Started/Configuration-File/
|
|
||||||
# Only uncomment the lines you want to use/modify
|
|
||||||
|
|
||||||
# exclude:
|
|
||||||
# platforms:
|
|
||||||
# - excluded_folder_a
|
|
||||||
# roms:
|
|
||||||
# single_file:
|
|
||||||
# extensions:
|
|
||||||
# - xml
|
|
||||||
# - txt
|
|
||||||
# names:
|
|
||||||
# - '._*'
|
|
||||||
# - '*.nfo'
|
|
||||||
# multi_file:
|
|
||||||
# names:
|
|
||||||
# - downloaded_media
|
|
||||||
# - media
|
|
||||||
|
|
||||||
# system:
|
|
||||||
# platforms:
|
|
||||||
# gc: ngc
|
|
||||||
# ps1: psx
|
|
||||||
|
|
||||||
# The folder name where your roms are located (relative to library path)
|
|
||||||
# filesystem:
|
|
||||||
# roms_folder: 'roms'
|
|
||||||
|
|
||||||
# scan:
|
|
||||||
# priority:
|
|
||||||
# metadata:
|
|
||||||
# - "igdb"
|
|
||||||
# - "moby"
|
|
||||||
# - "ss"
|
|
||||||
# - "ra"
|
|
||||||
# artwork:
|
|
||||||
# - "igdb"
|
|
||||||
# - "moby"
|
|
||||||
# - "ss"
|
|
||||||
# region:
|
|
||||||
# - "us"
|
|
||||||
# - "eu"
|
|
||||||
# - "jp"
|
|
||||||
# language:
|
|
||||||
# - "en"
|
|
||||||
# media:
|
|
||||||
# - box2d
|
|
||||||
# - box3d
|
|
||||||
# - screenshot
|
|
||||||
# - manual
|
|
||||||
|
|
||||||
# emulatorjs:
|
|
||||||
# debug: false
|
|
||||||
# cache_limit: null
|
|
||||||
EOF
|
|
||||||
chmod 644 /var/lib/romm/config/config.yml
|
|
||||||
msg_ok "Created configuration file"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "RAHasher" "RetroAchievements/RALibretro" "prebuild" "latest" "/opt/RALibretro" "RAHasher-x64-Linux-*.zip"
|
|
||||||
cp /opt/RALibretro/RAHasher /usr/bin/RAHasher
|
|
||||||
chmod +x /usr/bin/RAHasher
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "romm" "rommapp/romm"
|
|
||||||
|
|
||||||
msg_info "Creating environment file"
|
|
||||||
sed -i 's/^supervised no/supervised systemd/' /etc/redis/redis.conf
|
|
||||||
systemctl restart redis-server
|
|
||||||
systemctl enable -q --now redis-server
|
|
||||||
AUTH_SECRET_KEY=$(openssl rand -hex 32)
|
|
||||||
|
|
||||||
cat <<EOF >/opt/romm/.env
|
|
||||||
ROMM_BASE_PATH=/var/lib/romm
|
|
||||||
ROMM_CONFIG_PATH=/var/lib/romm/config/config.yml
|
|
||||||
WEB_CONCURRENCY=4
|
|
||||||
|
|
||||||
DB_HOST=127.0.0.1
|
|
||||||
DB_PORT=3306
|
|
||||||
DB_NAME=$MARIADB_DB_NAME
|
|
||||||
DB_USER=$MARIADB_DB_USER
|
|
||||||
DB_PASSWD=$MARIADB_DB_PASS
|
|
||||||
|
|
||||||
REDIS_HOST=127.0.0.1
|
|
||||||
REDIS_PORT=6379
|
|
||||||
|
|
||||||
ROMM_AUTH_SECRET_KEY=$AUTH_SECRET_KEY
|
|
||||||
DISABLE_DOWNLOAD_ENDPOINT_AUTH=false
|
|
||||||
DISABLE_CSRF_PROTECTION=false
|
|
||||||
|
|
||||||
ENABLE_RESCAN_ON_FILESYSTEM_CHANGE=true
|
|
||||||
RESCAN_ON_FILESYSTEM_CHANGE_DELAY=5
|
|
||||||
|
|
||||||
ENABLE_SCHEDULED_RESCAN=true
|
|
||||||
SCHEDULED_RESCAN_CRON=0 3 * * *
|
|
||||||
ENABLE_SCHEDULED_UPDATE_SWITCH_TITLEDB=true
|
|
||||||
SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON=0 4 * * *
|
|
||||||
|
|
||||||
LOGLEVEL=INFO
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod 600 /opt/romm/.env
|
|
||||||
msg_ok "Created environment file"
|
|
||||||
|
|
||||||
msg_info "Setting up RomM Backend"
|
|
||||||
cd /opt/romm
|
|
||||||
export UV_CONCURRENT_DOWNLOADS=1
|
|
||||||
$STD uv sync --all-extras
|
|
||||||
cd /opt/romm/backend
|
|
||||||
$STD uv run alembic upgrade head
|
|
||||||
msg_ok "Set up RomM Backend"
|
|
||||||
|
|
||||||
msg_info "Setting up RomM Frontend"
|
|
||||||
cd /opt/romm/frontend
|
|
||||||
$STD npm install
|
|
||||||
$STD npm run build
|
|
||||||
|
|
||||||
cp -rf /opt/romm/frontend/assets/* /opt/romm/frontend/dist/assets/
|
|
||||||
|
|
||||||
mkdir -p /opt/romm/frontend/dist/assets/romm
|
|
||||||
ln -sfn /var/lib/romm/resources /opt/romm/frontend/dist/assets/romm/resources
|
|
||||||
ln -sfn /var/lib/romm/assets /opt/romm/frontend/dist/assets/romm/assets
|
|
||||||
msg_ok "Set up RomM Frontend"
|
|
||||||
|
|
||||||
msg_info "Configuring Nginx"
|
|
||||||
cat <<'EOF' >/etc/nginx/sites-available/romm
|
|
||||||
upstream romm_backend {
|
|
||||||
server 127.0.0.1:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
map $http_upgrade $connection_upgrade {
|
|
||||||
default upgrade;
|
|
||||||
'' close;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name _;
|
|
||||||
root /opt/romm/frontend/dist;
|
|
||||||
client_max_body_size 0;
|
|
||||||
|
|
||||||
# Frontend SPA
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Static assets
|
|
||||||
location /assets {
|
|
||||||
alias /opt/romm/frontend/dist/assets;
|
|
||||||
try_files $uri $uri/ =404;
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
}
|
|
||||||
|
|
||||||
# EmulatorJS player - requires COOP/COEP headers for SharedArrayBuffer
|
|
||||||
location ~ ^/rom/.*/ejs$ {
|
|
||||||
add_header Cross-Origin-Embedder-Policy "require-corp";
|
|
||||||
add_header Cross-Origin-Opener-Policy "same-origin";
|
|
||||||
try_files $uri /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Backend API
|
|
||||||
location /api {
|
|
||||||
proxy_pass http://romm_backend;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_request_buffering off;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
# WebSocket and Netplay
|
|
||||||
location ~ ^/(ws|netplay) {
|
|
||||||
proxy_pass http://romm_backend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_read_timeout 86400;
|
|
||||||
}
|
|
||||||
|
|
||||||
# OpenAPI docs
|
|
||||||
location = /openapi.json {
|
|
||||||
proxy_pass http://romm_backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Internal library file serving
|
|
||||||
location /library/ {
|
|
||||||
internal;
|
|
||||||
alias /var/lib/romm/library/;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
|
||||||
ln -sf /etc/nginx/sites-available/romm /etc/nginx/sites-enabled/romm
|
|
||||||
systemctl restart nginx
|
|
||||||
systemctl enable -q --now nginx
|
|
||||||
msg_ok "Configured Nginx"
|
|
||||||
|
|
||||||
msg_info "Creating Services"
|
|
||||||
cat <<EOF >/etc/systemd/system/romm-backend.service
|
|
||||||
[Unit]
|
|
||||||
Description=RomM Backend
|
|
||||||
After=network.target mariadb.service redis-server.service
|
|
||||||
Requires=mariadb.service redis-server.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
WorkingDirectory=/opt/romm/backend
|
|
||||||
EnvironmentFile=/opt/romm/.env
|
|
||||||
Environment="PYTHONPATH=/opt/romm"
|
|
||||||
ExecStart=/opt/romm/.venv/bin/python main.py
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/romm-worker.service
|
|
||||||
[Unit]
|
|
||||||
Description=RomM RQ Worker
|
|
||||||
After=network.target mariadb.service redis-server.service romm-backend.service
|
|
||||||
Requires=mariadb.service redis-server.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
WorkingDirectory=/opt/romm/backend
|
|
||||||
EnvironmentFile=/opt/romm/.env
|
|
||||||
Environment="PYTHONPATH=/opt/romm/backend"
|
|
||||||
ExecStart=/opt/romm/.venv/bin/rq worker --path /opt/romm/backend --url redis://127.0.0.1:6379/0 high default low
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/romm-scheduler.service
|
|
||||||
[Unit]
|
|
||||||
Description=RomM RQ Scheduler
|
|
||||||
After=network.target mariadb.service redis-server.service romm-backend.service
|
|
||||||
Requires=mariadb.service redis-server.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
WorkingDirectory=/opt/romm/backend
|
|
||||||
EnvironmentFile=/opt/romm/.env
|
|
||||||
Environment="PYTHONPATH=/opt/romm/backend"
|
|
||||||
Environment="RQ_REDIS_HOST=127.0.0.1"
|
|
||||||
Environment="RQ_REDIS_PORT=6379"
|
|
||||||
ExecStart=/opt/romm/.venv/bin/rqscheduler --path /opt/romm/backend
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/romm-watcher.service
|
|
||||||
[Unit]
|
|
||||||
Description=RomM Filesystem Watcher
|
|
||||||
After=network.target romm-backend.service
|
|
||||||
Requires=romm-backend.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
WorkingDirectory=/opt/romm/backend
|
|
||||||
EnvironmentFile=/opt/romm/.env
|
|
||||||
Environment="PYTHONPATH=/opt/romm/backend"
|
|
||||||
ExecStart=/opt/romm/.venv/bin/watchfiles --target-type command '/opt/romm/.venv/bin/python watcher.py' /var/lib/romm/library
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl enable -q --now romm-backend romm-worker romm-scheduler romm-watcher
|
|
||||||
msg_ok "Created Services"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright (c) 2021-2026 community-scripts ORG
|
|
||||||
# Author: CrazyWolf13
|
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
||||||
# Source: https://docs.seerr.dev/
|
|
||||||
|
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
||||||
color
|
|
||||||
verb_ip6
|
|
||||||
catch_errors
|
|
||||||
setting_up_container
|
|
||||||
network_check
|
|
||||||
update_os
|
|
||||||
|
|
||||||
msg_info "Installing Dependencies"
|
|
||||||
$STD apt-get install -y build-essential
|
|
||||||
msg_ok "Installed Dependencies"
|
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "seerr" "seerr-team/seerr" "tarball"
|
|
||||||
pnpm_desired=$(grep -Po '"pnpm":\s*"\K[^"]+' /opt/seerr/package.json)
|
|
||||||
NODE_VERSION="22" NODE_MODULE="pnpm@$pnpm_desired" setup_nodejs
|
|
||||||
|
|
||||||
msg_info "Installing Seerr (Patience)"
|
|
||||||
export CYPRESS_INSTALL_BINARY=0
|
|
||||||
cd /opt/seerr
|
|
||||||
$STD pnpm install --frozen-lockfile
|
|
||||||
export NODE_OPTIONS="--max-old-space-size=3072"
|
|
||||||
$STD pnpm build
|
|
||||||
mkdir -p /etc/seerr/
|
|
||||||
cat <<EOF >/etc/seerr/seerr.conf
|
|
||||||
## Seerr's default port is 5055, if you want to use both, change this.
|
|
||||||
## specify on which port to listen
|
|
||||||
PORT=5055
|
|
||||||
|
|
||||||
## specify on which interface to listen, by default seerr listens on all interfaces
|
|
||||||
HOST=0.0.0.0
|
|
||||||
|
|
||||||
## Uncomment if you want to force Node.js to resolve IPv4 before IPv6 (advanced users only)
|
|
||||||
# FORCE_IPV4_FIRST=true
|
|
||||||
EOF
|
|
||||||
msg_ok "Installed Seerr"
|
|
||||||
|
|
||||||
msg_info "Creating Service"
|
|
||||||
cat <<EOF >/etc/systemd/system/seerr.service
|
|
||||||
[Unit]
|
|
||||||
Description=Seerr Service
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
EnvironmentFile=/etc/seerr/seerr.conf
|
|
||||||
Environment=NODE_ENV=production
|
|
||||||
Type=exec
|
|
||||||
Restart=on-failure
|
|
||||||
WorkingDirectory=/opt/seerr
|
|
||||||
ExecStart=/usr/bin/node dist/index.js
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
systemctl enable -q --now seerr
|
|
||||||
msg_ok "Created Service"
|
|
||||||
|
|
||||||
motd_ssh
|
|
||||||
customize
|
|
||||||
cleanup_lxc
|
|
||||||
@@ -29,7 +29,6 @@ $STD uv venv --clear
|
|||||||
$STD source /opt/Tautulli/.venv/bin/activate
|
$STD source /opt/Tautulli/.venv/bin/activate
|
||||||
$STD uv pip install -r requirements.txt
|
$STD uv pip install -r requirements.txt
|
||||||
$STD uv pip install pyopenssl
|
$STD uv pip install pyopenssl
|
||||||
$STD uv pip install "setuptools<81"
|
|
||||||
msg_ok "Installed Tautulli"
|
msg_ok "Installed Tautulli"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ SECRET="$(openssl rand -hex 64)"
|
|||||||
sed -e '/^NODE_ENV=/s/=.*$/=production/' \
|
sed -e '/^NODE_ENV=/s/=.*$/=production/' \
|
||||||
-e 's/^TUDUDI_USER/# TUDUDI_USER/g' \
|
-e 's/^TUDUDI_USER/# TUDUDI_USER/g' \
|
||||||
-e "/_SECRET=/s/=.*$/=${SECRET}/" \
|
-e "/_SECRET=/s/=.*$/=${SECRET}/" \
|
||||||
-e '/^# DB_FILE=/s/^# //' \
|
-e "/^# DB_FILE/s/^# //; \
|
||||||
-e "s|^DB_FILE=.*|DB_FILE=${DB_LOCATION}/production.sqlite3|" \
|
\|DB_FILE|s|/path.*$|${DB_LOCATION}/production.sqlite3|" \
|
||||||
-e "/^# TUDUDI_ALLOWED/s/^# //; \
|
-e "/^# TUDUDI_ALLOWED/s/^# //; \
|
||||||
\|_ORIGINS=|s|=.*$|=<your tududi IP or FDQN>|" \
|
\|_ORIGINS=|s|=.*$|=<your tududi IP or FDQN>|" \
|
||||||
-e "/^# TUDUDI_UPLOAD/s/^# //; \
|
-e "/^# TUDUDI_UPLOAD/s/^# //; \
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ fetch_and_deploy_gh_release "vaultwarden" "dani-garcia/vaultwarden" "tarball" "l
|
|||||||
|
|
||||||
msg_info "Building Vaultwarden (Patience)"
|
msg_info "Building Vaultwarden (Patience)"
|
||||||
cd /tmp/vaultwarden-src
|
cd /tmp/vaultwarden-src
|
||||||
VW_VERSION=$(get_latest_github_release "dani-garcia/vaultwarden")
|
|
||||||
export VW_VERSION
|
|
||||||
$STD cargo build --features "sqlite,mysql,postgresql" --release
|
$STD cargo build --features "sqlite,mysql,postgresql" --release
|
||||||
msg_ok "Built Vaultwarden"
|
msg_ok "Built Vaultwarden"
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,42 @@ EOF
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR
|
||||||
|
trap on_exit EXIT
|
||||||
|
trap on_interrupt INT
|
||||||
|
trap on_terminate TERM
|
||||||
|
|
||||||
|
error_handler() {
|
||||||
|
local exit_code="$1"
|
||||||
|
local line_number="$2"
|
||||||
|
local command="$3"
|
||||||
|
|
||||||
|
if [[ "$exit_code" -eq 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\e[?25h"
|
||||||
|
echo -e "\n${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}\n"
|
||||||
|
exit "$exit_code"
|
||||||
|
}
|
||||||
|
|
||||||
|
on_exit() {
|
||||||
|
local exit_code="$?"
|
||||||
|
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
|
||||||
|
exit "$exit_code"
|
||||||
|
}
|
||||||
|
|
||||||
|
on_interrupt() {
|
||||||
|
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}"
|
||||||
|
exit 130
|
||||||
|
}
|
||||||
|
|
||||||
|
on_terminate() {
|
||||||
|
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}"
|
||||||
|
exit 143
|
||||||
|
}
|
||||||
|
|
||||||
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
||||||
setting_up_container() {
|
setting_up_container() {
|
||||||
msg_info "Setting up Container OS"
|
msg_info "Setting up Container OS"
|
||||||
|
|||||||
@@ -34,19 +34,11 @@ net_resolves() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensure_usr_local_bin_persist() {
|
ensure_usr_local_bin_persist() {
|
||||||
# Login shells: /etc/profile.d/
|
|
||||||
local PROFILE_FILE="/etc/profile.d/10-localbin.sh"
|
local PROFILE_FILE="/etc/profile.d/10-localbin.sh"
|
||||||
if [ ! -f "$PROFILE_FILE" ]; then
|
if [ ! -f "$PROFILE_FILE" ]; then
|
||||||
echo 'case ":$PATH:" in *:/usr/local/bin:*) ;; *) export PATH="/usr/local/bin:$PATH";; esac' >"$PROFILE_FILE"
|
echo 'case ":$PATH:" in *:/usr/local/bin:*) ;; *) export PATH="/usr/local/bin:$PATH";; esac' >"$PROFILE_FILE"
|
||||||
chmod +x "$PROFILE_FILE"
|
chmod +x "$PROFILE_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Non-login shells (pct enter): /root/.profile and /root/.bashrc
|
|
||||||
for rc_file in /root/.profile /root/.bashrc; do
|
|
||||||
if [ -f "$rc_file" ] && ! grep -q '/usr/local/bin' "$rc_file"; then
|
|
||||||
echo 'export PATH="/usr/local/bin:$PATH"' >>"$rc_file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
download_with_progress() {
|
download_with_progress() {
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ detect_repo_source() {
|
|||||||
community-scripts/ProxmoxVED) REPO_SOURCE="ProxmoxVED" ;;
|
community-scripts/ProxmoxVED) REPO_SOURCE="ProxmoxVED" ;;
|
||||||
"")
|
"")
|
||||||
# No URL detected — use hardcoded fallback
|
# No URL detected — use hardcoded fallback
|
||||||
# This value must match the repo: ProxmoxVE for production, ProxmoxVED for dev
|
# CI sed transforms this on promotion: ProxmoxVED → ProxmoxVE
|
||||||
REPO_SOURCE="ProxmoxVE"
|
REPO_SOURCE="ProxmoxVED"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# Fork or unknown repo
|
# Fork or unknown repo
|
||||||
@@ -135,44 +135,19 @@ explain_exit_code() {
|
|||||||
# --- Generic / Shell ---
|
# --- Generic / Shell ---
|
||||||
1) echo "General error / Operation not permitted" ;;
|
1) echo "General error / Operation not permitted" ;;
|
||||||
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
||||||
10) echo "Docker / privileged mode required (unsupported environment)" ;;
|
|
||||||
|
|
||||||
# --- curl / wget errors (commonly seen in downloads) ---
|
# --- curl / wget errors (commonly seen in downloads) ---
|
||||||
4) echo "curl: Feature not supported or protocol error" ;;
|
|
||||||
5) echo "curl: Could not resolve proxy" ;;
|
|
||||||
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
||||||
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
||||||
8) echo "curl: FTP server reply error" ;;
|
|
||||||
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
||||||
23) echo "curl: Write error (disk full or permissions)" ;;
|
|
||||||
25) echo "curl: Upload failed" ;;
|
|
||||||
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
||||||
30) echo "curl: FTP port command failed" ;;
|
|
||||||
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
||||||
56) echo "curl: Receive error (connection reset by peer)" ;;
|
|
||||||
75) echo "Temporary failure (retry later)" ;;
|
|
||||||
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
|
|
||||||
|
|
||||||
# --- Package manager / APT / DPKG ---
|
# --- Package manager / APT / DPKG ---
|
||||||
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
||||||
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
||||||
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
||||||
|
|
||||||
# --- BSD sysexits.h (64-78) ---
|
|
||||||
64) echo "Usage error (wrong arguments)" ;;
|
|
||||||
65) echo "Data format error (bad input data)" ;;
|
|
||||||
66) echo "Input file not found (cannot open input)" ;;
|
|
||||||
67) echo "User not found (addressee unknown)" ;;
|
|
||||||
68) echo "Host not found (hostname unknown)" ;;
|
|
||||||
69) echo "Service unavailable" ;;
|
|
||||||
70) echo "Internal software error" ;;
|
|
||||||
71) echo "System error (OS-level failure)" ;;
|
|
||||||
72) echo "Critical OS file missing" ;;
|
|
||||||
73) echo "Cannot create output file" ;;
|
|
||||||
74) echo "I/O error" ;;
|
|
||||||
76) echo "Remote protocol error" ;;
|
|
||||||
77) echo "Permission denied" ;;
|
|
||||||
|
|
||||||
# --- Common shell/system errors ---
|
# --- Common shell/system errors ---
|
||||||
124) echo "Command timed out (timeout command)" ;;
|
124) echo "Command timed out (timeout command)" ;;
|
||||||
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
||||||
@@ -425,22 +400,26 @@ detect_cpu() {
|
|||||||
# - Detects RAM speed using dmidecode
|
# - Detects RAM speed using dmidecode
|
||||||
# - Sets RAM_SPEED global (e.g., "4800" for DDR5-4800)
|
# - Sets RAM_SPEED global (e.g., "4800" for DDR5-4800)
|
||||||
# - Requires root access for dmidecode
|
# - Requires root access for dmidecode
|
||||||
# - Returns empty if not available or if speed is "Unknown" (nested VMs)
|
# - Returns empty if not available
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
detect_ram() {
|
detect_ram() {
|
||||||
RAM_SPEED=""
|
RAM_SPEED=""
|
||||||
|
|
||||||
if command -v dmidecode &>/dev/null; then
|
if command -v dmidecode &>/dev/null; then
|
||||||
# Get configured memory speed (actual running speed)
|
# Get configured memory speed (actual running speed)
|
||||||
# Use || true to handle "Unknown" values in nested VMs (no numeric match)
|
RAM_SPEED=$(dmidecode -t memory 2>/dev/null | grep -m1 "Configured Memory Speed:" | grep -oE "[0-9]+" | head -1 || true)
|
||||||
RAM_SPEED=$(dmidecode -t memory 2>/dev/null | grep -m1 "Configured Memory Speed:" | grep -oE "[0-9]+" | head -1) || true
|
|
||||||
|
|
||||||
# Fallback to Speed: if Configured not available
|
# Fallback to Speed: if Configured not available
|
||||||
if [[ -z "$RAM_SPEED" ]]; then
|
if [[ -z "$RAM_SPEED" ]]; then
|
||||||
RAM_SPEED=$(dmidecode -t memory 2>/dev/null | grep -m1 "Speed:" | grep -oE "[0-9]+" | head -1) || true
|
RAM_SPEED=$(dmidecode -t memory 2>/dev/null | grep -m1 "Speed:" | grep -oE "[0-9]+" | head -1 || true)
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Ensure RAM_SPEED is a valid integer (PocketBase stores it as integer)
|
||||||
|
if [[ -z "$RAM_SPEED" || ! "$RAM_SPEED" =~ ^[0-9]+$ ]]; then
|
||||||
|
RAM_SPEED=0
|
||||||
|
fi
|
||||||
|
|
||||||
export RAM_SPEED
|
export RAM_SPEED
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +514,7 @@ post_to_api() {
|
|||||||
"gpu_vendor": "${gpu_vendor}",
|
"gpu_vendor": "${gpu_vendor}",
|
||||||
"gpu_model": "${gpu_model}",
|
"gpu_model": "${gpu_model}",
|
||||||
"gpu_passthrough": "${gpu_passthrough}",
|
"gpu_passthrough": "${gpu_passthrough}",
|
||||||
"ram_speed": "${ram_speed}",
|
"ram_speed": ${ram_speed:-0},
|
||||||
"repo_source": "${REPO_SOURCE}"
|
"repo_source": "${REPO_SOURCE}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -639,7 +618,7 @@ post_to_api_vm() {
|
|||||||
"gpu_vendor": "${gpu_vendor}",
|
"gpu_vendor": "${gpu_vendor}",
|
||||||
"gpu_model": "${gpu_model}",
|
"gpu_model": "${gpu_model}",
|
||||||
"gpu_passthrough": "${gpu_passthrough}",
|
"gpu_passthrough": "${gpu_passthrough}",
|
||||||
"ram_speed": "${ram_speed}",
|
"ram_speed": ${ram_speed:-0},
|
||||||
"repo_source": "${REPO_SOURCE}"
|
"repo_source": "${REPO_SOURCE}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -649,8 +628,6 @@ EOF
|
|||||||
curl -fsS -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
|
curl -fsS -m "${TELEMETRY_TIMEOUT}" -X POST "${TELEMETRY_URL}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "$JSON_PAYLOAD" &>/dev/null || true
|
-d "$JSON_PAYLOAD" &>/dev/null || true
|
||||||
|
|
||||||
POST_TO_API_DONE=true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -775,7 +752,7 @@ post_update_to_api() {
|
|||||||
"gpu_vendor": "${gpu_vendor}",
|
"gpu_vendor": "${gpu_vendor}",
|
||||||
"gpu_model": "${gpu_model}",
|
"gpu_model": "${gpu_model}",
|
||||||
"gpu_passthrough": "${gpu_passthrough}",
|
"gpu_passthrough": "${gpu_passthrough}",
|
||||||
"ram_speed": "${ram_speed}",
|
"ram_speed": ${ram_speed:-0},
|
||||||
"repo_source": "${REPO_SOURCE}"
|
"repo_source": "${REPO_SOURCE}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@@ -817,7 +794,7 @@ EOF
|
|||||||
"gpu_vendor": "${gpu_vendor}",
|
"gpu_vendor": "${gpu_vendor}",
|
||||||
"gpu_model": "${gpu_model}",
|
"gpu_model": "${gpu_model}",
|
||||||
"gpu_passthrough": "${gpu_passthrough}",
|
"gpu_passthrough": "${gpu_passthrough}",
|
||||||
"ram_speed": "${ram_speed}",
|
"ram_speed": ${ram_speed:-0},
|
||||||
"repo_source": "${REPO_SOURCE}"
|
"repo_source": "${REPO_SOURCE}"
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -5253,20 +5253,14 @@ ensure_log_on_host() {
|
|||||||
# - Exit trap handler for reporting to API telemetry
|
# - Exit trap handler for reporting to API telemetry
|
||||||
# - Captures exit code and reports to PocketBase using centralized error descriptions
|
# - Captures exit code and reports to PocketBase using centralized error descriptions
|
||||||
# - Uses explain_exit_code() from api.func for consistent error messages
|
# - Uses explain_exit_code() from api.func for consistent error messages
|
||||||
# - For non-zero exit codes: posts "failed" status
|
# - Posts failure status with exit code to API (error description resolved automatically)
|
||||||
# - For zero exit codes where post_update_to_api was never called:
|
# - Only executes on non-zero exit codes
|
||||||
# catches orphaned "installing" records (e.g., script exited cleanly
|
|
||||||
# but description() was never reached)
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
api_exit_script() {
|
api_exit_script() {
|
||||||
local exit_code=$?
|
exit_code=$?
|
||||||
if [ $exit_code -ne 0 ]; then
|
if [ $exit_code -ne 0 ]; then
|
||||||
ensure_log_on_host
|
ensure_log_on_host
|
||||||
post_update_to_api "failed" "$exit_code"
|
post_update_to_api "failed" "$exit_code"
|
||||||
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
# Script exited with 0 but never sent a completion status
|
|
||||||
# This catches edge cases like early returns after post_to_api()
|
|
||||||
post_update_to_api "failed" "1"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5274,5 +5268,5 @@ if command -v pveversion >/dev/null 2>&1; then
|
|||||||
trap 'api_exit_script' EXIT
|
trap 'api_exit_script' EXIT
|
||||||
fi
|
fi
|
||||||
trap 'ensure_log_on_host; post_update_to_api "failed" "$?"' ERR
|
trap 'ensure_log_on_host; post_update_to_api "failed" "$?"' ERR
|
||||||
trap 'ensure_log_on_host; post_update_to_api "failed" "130"; exit 130' SIGINT
|
trap 'ensure_log_on_host; post_update_to_api "failed" "130"' SIGINT
|
||||||
trap 'ensure_log_on_host; post_update_to_api "failed" "143"; exit 143' SIGTERM
|
trap 'ensure_log_on_host; post_update_to_api "failed" "143"' SIGTERM
|
||||||
|
|||||||
@@ -37,34 +37,11 @@ if ! declare -f explain_exit_code &>/dev/null; then
|
|||||||
case "$code" in
|
case "$code" in
|
||||||
1) echo "General error / Operation not permitted" ;;
|
1) echo "General error / Operation not permitted" ;;
|
||||||
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
||||||
10) echo "Docker / privileged mode required (unsupported environment)" ;;
|
|
||||||
4) echo "curl: Feature not supported or protocol error" ;;
|
|
||||||
5) echo "curl: Could not resolve proxy" ;;
|
|
||||||
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
||||||
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
||||||
8) echo "curl: FTP server reply error" ;;
|
|
||||||
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
||||||
23) echo "curl: Write error (disk full or permissions)" ;;
|
|
||||||
25) echo "curl: Upload failed" ;;
|
|
||||||
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
||||||
30) echo "curl: FTP port command failed" ;;
|
|
||||||
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
||||||
56) echo "curl: Receive error (connection reset by peer)" ;;
|
|
||||||
75) echo "Temporary failure (retry later)" ;;
|
|
||||||
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
|
|
||||||
64) echo "Usage error (wrong arguments)" ;;
|
|
||||||
65) echo "Data format error (bad input data)" ;;
|
|
||||||
66) echo "Input file not found (cannot open input)" ;;
|
|
||||||
67) echo "User not found (addressee unknown)" ;;
|
|
||||||
68) echo "Host not found (hostname unknown)" ;;
|
|
||||||
69) echo "Service unavailable" ;;
|
|
||||||
70) echo "Internal software error" ;;
|
|
||||||
71) echo "System error (OS-level failure)" ;;
|
|
||||||
72) echo "Critical OS file missing" ;;
|
|
||||||
73) echo "Cannot create output file" ;;
|
|
||||||
74) echo "I/O error" ;;
|
|
||||||
76) echo "Remote protocol error" ;;
|
|
||||||
77) echo "Permission denied" ;;
|
|
||||||
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
||||||
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
||||||
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ network_check() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
trap 'error_handler' ERR
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||||
}
|
}
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
@@ -1851,26 +1851,16 @@ function download_with_progress() {
|
|||||||
# Ensures /usr/local/bin is permanently in system PATH.
|
# Ensures /usr/local/bin is permanently in system PATH.
|
||||||
#
|
#
|
||||||
# Description:
|
# Description:
|
||||||
# - Adds to /etc/profile.d for login shells (SSH, noVNC)
|
# - Adds to /etc/profile.d if not present
|
||||||
# - Adds to /root/.bashrc for non-login shells (pct enter)
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
function ensure_usr_local_bin_persist() {
|
function ensure_usr_local_bin_persist() {
|
||||||
# Skip on Proxmox host
|
|
||||||
command -v pveversion &>/dev/null && return
|
|
||||||
|
|
||||||
# Login shells: /etc/profile.d/
|
|
||||||
local PROFILE_FILE="/etc/profile.d/custom_path.sh"
|
local PROFILE_FILE="/etc/profile.d/custom_path.sh"
|
||||||
if [[ ! -f "$PROFILE_FILE" ]]; then
|
|
||||||
|
if [[ ! -f "$PROFILE_FILE" ]] && ! command -v pveversion &>/dev/null; then
|
||||||
echo 'export PATH="/usr/local/bin:$PATH"' >"$PROFILE_FILE"
|
echo 'export PATH="/usr/local/bin:$PATH"' >"$PROFILE_FILE"
|
||||||
chmod +x "$PROFILE_FILE"
|
chmod +x "$PROFILE_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Non-login shells (pct enter): /root/.bashrc
|
|
||||||
local BASHRC="/root/.bashrc"
|
|
||||||
if [[ -f "$BASHRC" ]] && ! grep -q '/usr/local/bin' "$BASHRC"; then
|
|
||||||
echo 'export PATH="/usr/local/bin:$PATH"' >>"$BASHRC"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -529,21 +529,9 @@ cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
if [[ "$(dirs -p | wc -l)" -gt 1 ]]; then
|
if [[ "$(dirs -p | wc -l)" -gt 1 ]]; then
|
||||||
popd >/dev/null || true
|
popd >/dev/null || true
|
||||||
fi
|
fi
|
||||||
# Report final telemetry status if post_to_api_vm was called but no update was sent
|
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if declare -f post_update_to_api >/dev/null 2>&1; then
|
|
||||||
if [[ $exit_code -ne 0 ]]; then
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
else
|
|
||||||
# Exited cleanly but description()/success was never called — shouldn't happen
|
|
||||||
post_update_to_api "failed" "1"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root() {
|
check_root() {
|
||||||
|
|||||||
@@ -100,15 +100,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,15 +100,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,15 +100,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,16 +104,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
# Only send telemetry if post_to_api_vm was called (installing status was sent)
|
post_update_to_api "done" "none"
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,15 +101,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,15 +100,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,15 +105,7 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,15 +79,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,15 +101,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,15 +109,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,15 +97,7 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,15 +100,7 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,15 +99,7 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,15 +99,8 @@ function cleanup_vmid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
local exit_code=$?
|
|
||||||
popd >/dev/null
|
popd >/dev/null
|
||||||
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
post_update_to_api "done" "none"
|
||||||
if [[ $exit_code -eq 0 ]]; then
|
|
||||||
post_update_to_api "done" "none"
|
|
||||||
else
|
|
||||||
post_update_to_api "failed" "$exit_code"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -rf $TEMP_DIR
|
rm -rf $TEMP_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user