mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-03-19 00:13:01 +01:00
Compare commits
1 Commits
fix/tdarr-
...
feature/au
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08e3169e17 |
10
.github/workflows/delete-pocketbase-entry-on-removal.yml
generated
vendored
10
.github/workflows/delete-pocketbase-entry-on-removal.yml
generated
vendored
@@ -75,8 +75,7 @@ jobs:
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
|
||||
function request(fullUrl, opts, redirectCount) {
|
||||
redirectCount = redirectCount || 0;
|
||||
function request(fullUrl, opts) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const u = url.parse(fullUrl);
|
||||
const isHttps = u.protocol === 'https:';
|
||||
@@ -91,13 +90,6 @@ jobs:
|
||||
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||
const lib = isHttps ? https : http;
|
||||
const req = lib.request(options, function(res) {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||
res.resume();
|
||||
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||
return;
|
||||
}
|
||||
let data = '';
|
||||
res.on('data', function(chunk) { data += chunk; });
|
||||
res.on('end', function() {
|
||||
|
||||
24
.github/workflows/push-json-to-pocketbase.yml
generated
vendored
24
.github/workflows/push-json-to-pocketbase.yml
generated
vendored
@@ -48,8 +48,7 @@ jobs:
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
function request(fullUrl, opts, redirectCount) {
|
||||
redirectCount = redirectCount || 0;
|
||||
function request(fullUrl, opts) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const u = url.parse(fullUrl);
|
||||
const isHttps = u.protocol === 'https:';
|
||||
@@ -64,13 +63,6 @@ jobs:
|
||||
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||
const lib = isHttps ? https : http;
|
||||
const req = lib.request(options, function(res) {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||
res.resume();
|
||||
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||
return;
|
||||
}
|
||||
let data = '';
|
||||
res.on('data', function(chunk) { data += chunk; });
|
||||
res.on('end', function() {
|
||||
@@ -133,15 +125,15 @@ jobs:
|
||||
var osVersionToId = {};
|
||||
try {
|
||||
const res = await request(apiBase + '/collections/z_ref_note_types/records?perPage=500', { headers: { 'Authorization': token } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) { noteTypeToId[item.type] = item.id; noteTypeToId[item.type.toLowerCase()] = item.id; } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) noteTypeToId[item.type] = item.id; });
|
||||
} catch (e) { console.warn('z_ref_note_types:', e.message); }
|
||||
try {
|
||||
const res = await request(apiBase + '/collections/z_ref_install_method_types/records?perPage=500', { headers: { 'Authorization': token } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) { installMethodTypeToId[item.type] = item.id; installMethodTypeToId[item.type.toLowerCase()] = item.id; } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.type != null) installMethodTypeToId[item.type] = item.id; });
|
||||
} catch (e) { console.warn('z_ref_install_method_types:', e.message); }
|
||||
try {
|
||||
const res = await request(apiBase + '/collections/z_ref_os/records?perPage=500', { headers: { 'Authorization': token } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.os != null) { osToId[item.os] = item.id; osToId[item.os.toLowerCase()] = item.id; } });
|
||||
if (res.ok) JSON.parse(res.body).items?.forEach(function(item) { if (item.os != null) osToId[item.os] = item.id; });
|
||||
} catch (e) { console.warn('z_ref_os:', e.message); }
|
||||
try {
|
||||
const res = await request(apiBase + '/collections/z_ref_os_version/records?perPage=500&expand=os', { headers: { 'Authorization': token } });
|
||||
@@ -162,7 +154,7 @@ jobs:
|
||||
name: data.name,
|
||||
slug: data.slug,
|
||||
script_created: data.date_created || data.script_created,
|
||||
script_updated: new Date().toISOString().split('T')[0],
|
||||
script_updated: data.date_created || data.script_updated,
|
||||
updateable: data.updateable,
|
||||
privileged: data.privileged,
|
||||
port: data.interface_port != null ? data.interface_port : data.port,
|
||||
@@ -171,8 +163,8 @@ jobs:
|
||||
logo: data.logo,
|
||||
description: data.description,
|
||||
config_path: data.config_path,
|
||||
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user || null,
|
||||
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd || null,
|
||||
default_user: (data.default_credentials && data.default_credentials.username) || data.default_user,
|
||||
default_passwd: (data.default_credentials && data.default_credentials.password) || data.default_passwd,
|
||||
is_dev: false
|
||||
};
|
||||
var resolvedType = typeValueToId[data.type];
|
||||
@@ -198,7 +190,7 @@ jobs:
|
||||
var postRes = await request(notesCollUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ text: note.text || '', type: typeId, script: scriptId })
|
||||
body: JSON.stringify({ text: note.text || '', type: typeId })
|
||||
});
|
||||
if (postRes.ok) noteIds.push(JSON.parse(postRes.body).id);
|
||||
}
|
||||
|
||||
12
.github/workflows/update-script-timestamp-on-sh-change.yml
generated
vendored
12
.github/workflows/update-script-timestamp-on-sh-change.yml
generated
vendored
@@ -83,8 +83,7 @@ jobs:
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
|
||||
function request(fullUrl, opts, redirectCount) {
|
||||
redirectCount = redirectCount || 0;
|
||||
function request(fullUrl, opts) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const u = url.parse(fullUrl);
|
||||
const isHttps = u.protocol === 'https:';
|
||||
@@ -99,13 +98,6 @@ jobs:
|
||||
if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
|
||||
const lib = isHttps ? https : http;
|
||||
const req = lib.request(options, function(res) {
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
|
||||
const redirectUrl = url.resolve(fullUrl, res.headers.location);
|
||||
res.resume();
|
||||
resolve(request(redirectUrl, opts, redirectCount + 1));
|
||||
return;
|
||||
}
|
||||
let data = '';
|
||||
res.on('data', function(chunk) { data += chunk; });
|
||||
res.on('end', function() {
|
||||
@@ -159,7 +151,7 @@ jobs:
|
||||
method: 'PATCH',
|
||||
headers: { 'Authorization': token, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
script_updated: new Date().toISOString().split('T')[0],
|
||||
name: record.name || record.slug,
|
||||
last_update_commit: process.env.PR_URL || process.env.COMMIT_URL || ''
|
||||
})
|
||||
});
|
||||
|
||||
@@ -427,7 +427,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Split-Pro ([#12975](https://github.com/community-scripts/ProxmoxVE/pull/12975))
|
||||
- split-pro ([#12975](https://github.com/community-scripts/ProxmoxVE/pull/12975))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
@@ -436,21 +436,14 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
- Paperless-NGX: increase default RAM to 3GB [@MickLesk](https://github.com/MickLesk) ([#13018](https://github.com/community-scripts/ProxmoxVE/pull/13018))
|
||||
- Plex: restart service after update to apply new version [@MickLesk](https://github.com/MickLesk) ([#13017](https://github.com/community-scripts/ProxmoxVE/pull/13017))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools: centralize GPU group setup via setup_hwaccel [@MickLesk](https://github.com/MickLesk) ([#13044](https://github.com/community-scripts/ProxmoxVE/pull/13044))
|
||||
- Termix: add guacd build and systemd integration [@MickLesk](https://github.com/MickLesk) ([#12999](https://github.com/community-scripts/ProxmoxVE/pull/12999))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Refactor: Jellyfin repo, ffmpeg package and symlinks [@MickLesk](https://github.com/MickLesk) ([#13045](https://github.com/community-scripts/ProxmoxVE/pull/13045))
|
||||
- pve-scripts-local: Increase default disk size from 4GB to 10GB [@MickLesk](https://github.com/MickLesk) ([#13009](https://github.com/community-scripts/ProxmoxVE/pull/13009))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func Implement pg_cron setup for setup_postgresql [@MickLesk](https://github.com/MickLesk) ([#13053](https://github.com/community-scripts/ProxmoxVE/pull/13053))
|
||||
- tools.func: Implement check_for_gh_tag function [@MickLesk](https://github.com/MickLesk) ([#12998](https://github.com/community-scripts/ProxmoxVE/pull/12998))
|
||||
- tools.func: Implement fetch_and_deploy_gh_tag function [@MickLesk](https://github.com/MickLesk) ([#13000](https://github.com/community-scripts/ProxmoxVE/pull/13000))
|
||||
|
||||
|
||||
@@ -39,23 +39,14 @@ function update_script() {
|
||||
msg_ok "Updated Intel Dependencies"
|
||||
fi
|
||||
|
||||
msg_info "Setting up Jellyfin Repository"
|
||||
setup_deb822_repo \
|
||||
"jellyfin" \
|
||||
"https://repo.jellyfin.org/jellyfin_team.gpg.key" \
|
||||
"https://repo.jellyfin.org/$(get_os_info id)" \
|
||||
"$(get_os_info codename)"
|
||||
msg_ok "Set up Jellyfin Repository"
|
||||
|
||||
msg_info "Updating Jellyfin"
|
||||
ensure_dependencies libjemalloc2
|
||||
if [[ ! -f /usr/lib/libjemalloc.so ]]; then
|
||||
ln -sf /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so
|
||||
fi
|
||||
$STD apt update
|
||||
$STD apt -y upgrade
|
||||
$STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server jellyfin-ffmpeg7
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe /usr/bin/ffprobe
|
||||
$STD apt -y --with-new-pkgs upgrade jellyfin jellyfin-server
|
||||
msg_ok "Updated Jellyfin"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
|
||||
@@ -33,16 +33,12 @@ function update_script() {
|
||||
$STD apt upgrade -y
|
||||
rm -rf /opt/tdarr/Tdarr_Updater
|
||||
cd /opt/tdarr
|
||||
RELEASE=$(curl_with_retry "https://f000.backblazeb2.com/file/tdarrs/versions.json" "-" | grep -oP '(?<="Tdarr_Updater": ")[^"]+' | grep linux_x64 | head -n 1)
|
||||
curl_with_retry "$RELEASE" "Tdarr_Updater.zip"
|
||||
RELEASE=$(curl -fsSL https://f000.backblazeb2.com/file/tdarrs/versions.json | grep -oP '(?<="Tdarr_Updater": ")[^"]+' | grep linux_x64 | head -n 1)
|
||||
curl -fsSL "$RELEASE" -o Tdarr_Updater.zip
|
||||
$STD unzip Tdarr_Updater.zip
|
||||
chmod +x Tdarr_Updater
|
||||
$STD ./Tdarr_Updater
|
||||
rm -rf /opt/tdarr/Tdarr_Updater.zip
|
||||
[[ -f /opt/tdarr/Tdarr_Server/Tdarr_Server ]] || {
|
||||
msg_error "Tdarr_Updater failed — tdarr.io may be blocked by local DNS"
|
||||
exit 250
|
||||
}
|
||||
msg_ok "Updated Tdarr"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
|
||||
116
ct/termix.sh
116
ct/termix.sh
@@ -29,116 +29,10 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_tag "guacd" "apache/guacamole-server"; then
|
||||
msg_info "Stopping guacd"
|
||||
systemctl stop guacd 2>/dev/null || true
|
||||
msg_ok "Stopped guacd"
|
||||
|
||||
ensure_dependencies \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
libtool-bin \
|
||||
uuid-dev \
|
||||
libvncserver-dev \
|
||||
freerdp3-dev \
|
||||
libssh2-1-dev \
|
||||
libtelnet-dev \
|
||||
libwebsockets-dev \
|
||||
libpulse-dev \
|
||||
libvorbis-dev \
|
||||
libwebp-dev \
|
||||
libssl-dev \
|
||||
libpango1.0-dev \
|
||||
libswscale-dev \
|
||||
libavcodec-dev \
|
||||
libavutil-dev \
|
||||
libavformat-dev
|
||||
|
||||
msg_info "Updating Guacamole Server (guacd)"
|
||||
fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "${CHECK_UPDATE_RELEASE}" "/opt/guacamole-server"
|
||||
cd /opt/guacamole-server
|
||||
export CPPFLAGS="-Wno-error=deprecated-declarations"
|
||||
$STD autoreconf -fi
|
||||
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
|
||||
$STD make
|
||||
$STD make install
|
||||
$STD ldconfig
|
||||
cd /opt
|
||||
rm -rf /opt/guacamole-server
|
||||
msg_ok "Updated Guacamole Server (guacd) to ${CHECK_UPDATE_RELEASE}"
|
||||
|
||||
if [[ ! -f /etc/guacamole/guacd.conf ]]; then
|
||||
mkdir -p /etc/guacamole
|
||||
cat <<EOF >/etc/guacamole/guacd.conf
|
||||
[server]
|
||||
bind_host = 127.0.0.1
|
||||
bind_port = 4822
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ ! -f /etc/systemd/system/guacd.service ]] || grep -q "Type=forking" /etc/systemd/system/guacd.service 2>/dev/null; then
|
||||
cat <<EOF >/etc/systemd/system/guacd.service
|
||||
[Unit]
|
||||
Description=Guacamole Proxy Daemon (guacd)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! grep -q "guacd.service" /etc/systemd/system/termix.service 2>/dev/null; then
|
||||
sed -i '/^After=network.target/s/$/ guacd.service/' /etc/systemd/system/termix.service
|
||||
sed -i '/^\[Unit\]/a Wants=guacd.service' /etc/systemd/system/termix.service
|
||||
fi
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable -q --now guacd
|
||||
fi
|
||||
|
||||
if check_for_gh_release "termix" "Termix-SSH/Termix"; then
|
||||
msg_info "Stopping Termix"
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop termix
|
||||
msg_ok "Stopped Termix"
|
||||
|
||||
msg_info "Migrating Configuration"
|
||||
if [[ ! -f /opt/termix/.env ]]; then
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
fi
|
||||
if ! grep -q "EnvironmentFile" /etc/systemd/system/termix.service 2>/dev/null; then
|
||||
cat <<EOF >/etc/systemd/system/termix.service
|
||||
[Unit]
|
||||
Description=Termix Backend
|
||||
After=network.target guacd.service
|
||||
Wants=guacd.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/termix
|
||||
EnvironmentFile=/opt/termix/.env
|
||||
ExecStart=/usr/bin/node /opt/termix/dist/backend/backend/starter.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
msg_ok "Migrated Configuration"
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Backing up Data"
|
||||
cp -r /opt/termix/data /opt/termix_data_backup
|
||||
@@ -201,16 +95,16 @@ EOF
|
||||
sed -i 's|/app/html|/opt/termix/html|g' /etc/nginx/nginx.conf
|
||||
sed -i 's|/app/nginx|/opt/termix/nginx|g' /etc/nginx/nginx.conf
|
||||
sed -i 's|listen ${PORT};|listen 80;|g' /etc/nginx/nginx.conf
|
||||
|
||||
|
||||
nginx -t && systemctl reload nginx
|
||||
msg_ok "Updated Nginx Configuration"
|
||||
else
|
||||
msg_warn "Nginx configuration not updated. If Termix doesn't work, restore from backup or update manually."
|
||||
fi
|
||||
|
||||
msg_info "Starting Termix"
|
||||
msg_info "Starting Service"
|
||||
systemctl start termix
|
||||
msg_ok "Started Termix"
|
||||
msg_ok "Started Service"
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
exit
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://jellyfin.org/
|
||||
|
||||
@@ -14,30 +14,31 @@ network_check
|
||||
update_os
|
||||
|
||||
msg_custom "ℹ️" "${GN}" "If NVIDIA GPU passthrough is detected, you'll be asked whether to install drivers in the container"
|
||||
setup_hwaccel "jellyfin"
|
||||
setup_hwaccel
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
ensure_dependencies libjemalloc2
|
||||
msg_info "Installing Jellyfin"
|
||||
VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
|
||||
if ! dpkg -s libjemalloc2 >/dev/null 2>&1; then
|
||||
$STD apt install -y libjemalloc2
|
||||
fi
|
||||
if [[ ! -f /usr/lib/libjemalloc.so ]]; then
|
||||
ln -sf /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 /usr/lib/libjemalloc.so
|
||||
fi
|
||||
msg_ok "Installed Dependencies"
|
||||
if [[ ! -d /etc/apt/keyrings ]]; then
|
||||
mkdir -p /etc/apt/keyrings
|
||||
fi
|
||||
curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | gpg --dearmor --yes --output /etc/apt/keyrings/jellyfin.gpg
|
||||
cat <<EOF >/etc/apt/sources.list.d/jellyfin.sources
|
||||
Types: deb
|
||||
URIs: https://repo.jellyfin.org/${PCT_OSTYPE}
|
||||
Suites: ${VERSION}
|
||||
Components: main
|
||||
Architectures: amd64
|
||||
Signed-By: /etc/apt/keyrings/jellyfin.gpg
|
||||
EOF
|
||||
|
||||
msg_info "Setting up Jellyfin Repository"
|
||||
setup_deb822_repo \
|
||||
"jellyfin" \
|
||||
"https://repo.jellyfin.org/jellyfin_team.gpg.key" \
|
||||
"https://repo.jellyfin.org/$(get_os_info id)" \
|
||||
"$(get_os_info codename)"
|
||||
msg_ok "Set up Jellyfin Repository"
|
||||
|
||||
msg_info "Installing Jellyfin"
|
||||
$STD apt install -y jellyfin jellyfin-ffmpeg7
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg
|
||||
ln -sf /usr/lib/jellyfin-ffmpeg/ffprobe /usr/bin/ffprobe
|
||||
msg_ok "Installed Jellyfin"
|
||||
|
||||
msg_info "Configuring Jellyfin"
|
||||
$STD apt update
|
||||
$STD apt install -y jellyfin
|
||||
# Configure log rotation to prevent disk fill (keeps fail2ban compatibility) (PR: #1690 / Issue: #11224)
|
||||
cat <<EOF >/etc/logrotate.d/jellyfin
|
||||
/var/log/jellyfin/*.log {
|
||||
@@ -54,7 +55,12 @@ EOF
|
||||
chown -R jellyfin:adm /etc/jellyfin
|
||||
sleep 10
|
||||
systemctl restart jellyfin
|
||||
msg_ok "Configured Jellyfin"
|
||||
if [[ "$CTTYPE" == "0" ]]; then
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:root,jellyfin/' -e 's/^render:x:108:root,jellyfin$/ssl-cert:x:108:/' /etc/group
|
||||
else
|
||||
sed -i -e 's/^ssl-cert:x:104:$/render:x:104:jellyfin/' -e 's/^render:x:108:jellyfin$/ssl-cert:x:108:/' /etc/group
|
||||
fi
|
||||
msg_ok "Installed Jellyfin"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
@@ -20,16 +20,12 @@ msg_ok "Installed Dependencies"
|
||||
msg_info "Installing Tdarr"
|
||||
mkdir -p /opt/tdarr
|
||||
cd /opt/tdarr
|
||||
RELEASE=$(curl_with_retry "https://f000.backblazeb2.com/file/tdarrs/versions.json" "-" | grep -oP '(?<="Tdarr_Updater": ")[^"]+' | grep linux_x64 | head -n 1)
|
||||
curl_with_retry "$RELEASE" "Tdarr_Updater.zip"
|
||||
RELEASE=$(curl -fsSL https://f000.backblazeb2.com/file/tdarrs/versions.json | grep -oP '(?<="Tdarr_Updater": ")[^"]+' | grep linux_x64 | head -n 1)
|
||||
curl -fsSL "$RELEASE" -o Tdarr_Updater.zip
|
||||
$STD unzip Tdarr_Updater.zip
|
||||
chmod +x Tdarr_Updater
|
||||
$STD ./Tdarr_Updater
|
||||
rm -rf /opt/tdarr/Tdarr_Updater.zip
|
||||
[[ -f /opt/tdarr/Tdarr_Server/Tdarr_Server ]] || {
|
||||
msg_error "Tdarr_Updater failed — tdarr.io may be blocked by local DNS"
|
||||
exit 250
|
||||
}
|
||||
msg_ok "Installed Tdarr"
|
||||
|
||||
setup_hwaccel
|
||||
|
||||
@@ -19,41 +19,9 @@ $STD apt install -y \
|
||||
python3 \
|
||||
nginx \
|
||||
openssl \
|
||||
gettext-base \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
libtool-bin \
|
||||
uuid-dev \
|
||||
libvncserver-dev \
|
||||
freerdp3-dev \
|
||||
libssh2-1-dev \
|
||||
libtelnet-dev \
|
||||
libwebsockets-dev \
|
||||
libpulse-dev \
|
||||
libvorbis-dev \
|
||||
libwebp-dev \
|
||||
libssl-dev \
|
||||
libpango1.0-dev \
|
||||
libswscale-dev \
|
||||
libavcodec-dev \
|
||||
libavutil-dev \
|
||||
libavformat-dev
|
||||
gettext-base
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Building Guacamole Server (guacd)"
|
||||
fetch_and_deploy_gh_tag "guacd" "apache/guacamole-server" "latest" "/opt/guacamole-server"
|
||||
cd /opt/guacamole-server
|
||||
export CPPFLAGS="-Wno-error=deprecated-declarations"
|
||||
$STD autoreconf -fi
|
||||
$STD ./configure --with-init-dir=/etc/init.d --enable-allow-freerdp-snapshots
|
||||
$STD make
|
||||
$STD make install
|
||||
$STD ldconfig
|
||||
cd /opt
|
||||
rm -rf /opt/guacamole-server
|
||||
msg_ok "Built Guacamole Server (guacd)"
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix"
|
||||
|
||||
@@ -106,46 +74,17 @@ systemctl reload nginx
|
||||
msg_ok "Configured Nginx"
|
||||
|
||||
msg_info "Creating Service"
|
||||
mkdir -p /etc/guacamole
|
||||
cat <<EOF >/etc/guacamole/guacd.conf
|
||||
[server]
|
||||
bind_host = 127.0.0.1
|
||||
bind_port = 4822
|
||||
EOF
|
||||
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
|
||||
cat <<EOF >/etc/systemd/system/guacd.service
|
||||
[Unit]
|
||||
Description=Guacamole Proxy Daemon (guacd)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat <<EOF >/etc/systemd/system/termix.service
|
||||
[Unit]
|
||||
Description=Termix Backend
|
||||
After=network.target guacd.service
|
||||
Wants=guacd.service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/termix
|
||||
EnvironmentFile=/opt/termix/.env
|
||||
Environment=NODE_ENV=production
|
||||
Environment=DATA_DIR=/opt/termix/data
|
||||
ExecStart=/usr/bin/node /opt/termix/dist/backend/backend/starter.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
@@ -153,7 +92,7 @@ RestartSec=5
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now guacd termix
|
||||
systemctl enable -q --now termix
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -1979,47 +1979,6 @@ extract_version_from_json() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get latest GitHub tag (for repos that only publish tags, not releases).
|
||||
#
|
||||
# Usage:
|
||||
# get_latest_gh_tag "owner/repo" [prefix]
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - GitHub repo (owner/repo)
|
||||
# $2 - Optional prefix filter (e.g., "v" to only match tags starting with "v")
|
||||
#
|
||||
# Returns:
|
||||
# Latest tag name (stdout), or returns 1 on failure
|
||||
# ------------------------------------------------------------------------------
|
||||
get_latest_gh_tag() {
|
||||
local repo="$1"
|
||||
local prefix="${2:-}"
|
||||
local temp_file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
if ! github_api_call "https://api.github.com/repos/${repo}/tags?per_page=50" "$temp_file"; then
|
||||
rm -f "$temp_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local tag=""
|
||||
if [[ -n "$prefix" ]]; then
|
||||
tag=$(jq -r --arg p "$prefix" '[.[] | select(.name | startswith($p))][0].name // empty' "$temp_file")
|
||||
else
|
||||
tag=$(jq -r '.[0].name // empty' "$temp_file")
|
||||
fi
|
||||
|
||||
rm -f "$temp_file"
|
||||
|
||||
if [[ -z "$tag" ]]; then
|
||||
msg_error "No tags found for ${repo}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$tag"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Get latest GitHub release version with fallback to tags
|
||||
# Usage: get_latest_github_release "owner/repo" [strip_v] [include_prerelease]
|
||||
@@ -6698,38 +6657,22 @@ EOF
|
||||
# - Optionally uses official PGDG repository for specific versions
|
||||
# - Detects existing PostgreSQL version
|
||||
# - Dumps all databases before upgrade
|
||||
# - Installs optional PG_MODULES (e.g. postgis, contrib, cron)
|
||||
# - Installs optional PG_MODULES (e.g. postgis, contrib)
|
||||
# - Restores dumped data post-upgrade
|
||||
#
|
||||
# Variables:
|
||||
# USE_PGDG_REPO - Use official PGDG repository (default: true)
|
||||
# Set to "false" to use distro packages instead
|
||||
# PG_VERSION - Major PostgreSQL version (e.g. 15, 16) (default: 16)
|
||||
# PG_MODULES - Comma-separated list of modules (e.g. "postgis,contrib,cron")
|
||||
# PG_MODULES - Comma-separated list of modules (e.g. "postgis,contrib")
|
||||
#
|
||||
# Examples:
|
||||
# setup_postgresql # Uses PGDG repo, PG 16
|
||||
# PG_VERSION="17" setup_postgresql # Specific version from PGDG
|
||||
# USE_PGDG_REPO=false setup_postgresql # Uses distro package instead
|
||||
# PG_VERSION="17" PG_MODULES="cron" setup_postgresql # With pg_cron module
|
||||
# setup_postgresql # Uses PGDG repo, PG 16
|
||||
# PG_VERSION="17" setup_postgresql # Specific version from PGDG
|
||||
# USE_PGDG_REPO=false setup_postgresql # Uses distro package instead
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Internal helper: Configure shared_preload_libraries for pg_cron
|
||||
_configure_pg_cron_preload() {
|
||||
local modules="${1:-}"
|
||||
[[ -z "$modules" ]] && return 0
|
||||
if [[ ",$modules," == *",cron,"* ]]; then
|
||||
local current_libs
|
||||
current_libs=$(sudo -u postgres psql -tAc "SHOW shared_preload_libraries;" 2>/dev/null || echo "")
|
||||
if [[ "$current_libs" != *"pg_cron"* ]]; then
|
||||
local new_libs="${current_libs:+${current_libs},}pg_cron"
|
||||
$STD sudo -u postgres psql -c "ALTER SYSTEM SET shared_preload_libraries = '${new_libs}';"
|
||||
$STD systemctl restart postgresql
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
setup_postgresql() {
|
||||
function setup_postgresql() {
|
||||
local PG_VERSION="${PG_VERSION:-16}"
|
||||
local PG_MODULES="${PG_MODULES:-}"
|
||||
local USE_PGDG_REPO="${USE_PGDG_REPO:-true}"
|
||||
@@ -6767,7 +6710,6 @@ setup_postgresql() {
|
||||
$STD apt install -y "postgresql-${CURRENT_PG_VERSION}-${module}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
_configure_pg_cron_preload "$PG_MODULES"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -6803,7 +6745,6 @@ setup_postgresql() {
|
||||
$STD apt install -y "postgresql-${INSTALLED_VERSION}-${module}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
_configure_pg_cron_preload "$PG_MODULES"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -6825,7 +6766,6 @@ setup_postgresql() {
|
||||
$STD apt install -y "postgresql-${PG_VERSION}-${module}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
_configure_pg_cron_preload "$PG_MODULES"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -6853,16 +6793,13 @@ setup_postgresql() {
|
||||
local SUITE
|
||||
case "$DISTRO_CODENAME" in
|
||||
trixie | forky | sid)
|
||||
|
||||
if verify_repo_available "https://apt.postgresql.org/pub/repos/apt" "trixie-pgdg"; then
|
||||
SUITE="trixie-pgdg"
|
||||
|
||||
else
|
||||
msg_warn "PGDG repo not available for ${DISTRO_CODENAME}, falling back to distro packages"
|
||||
USE_PGDG_REPO=false setup_postgresql
|
||||
return $?
|
||||
fi
|
||||
|
||||
;;
|
||||
*)
|
||||
SUITE=$(get_fallback_suite "$DISTRO_ID" "$DISTRO_CODENAME" "https://apt.postgresql.org/pub/repos/apt")
|
||||
@@ -6946,7 +6883,6 @@ setup_postgresql() {
|
||||
}
|
||||
done
|
||||
fi
|
||||
_configure_pg_cron_preload "$PG_MODULES"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -6965,7 +6901,6 @@ setup_postgresql() {
|
||||
# PG_DB_NAME="immich" PG_DB_USER="immich" PG_DB_EXTENSIONS="pgvector" setup_postgresql_db
|
||||
# PG_DB_NAME="ghostfolio" PG_DB_USER="ghostfolio" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
|
||||
# PG_DB_NAME="adventurelog" PG_DB_USER="adventurelog" PG_DB_EXTENSIONS="postgis" setup_postgresql_db
|
||||
# PG_DB_NAME="splitpro" PG_DB_USER="splitpro" PG_DB_EXTENSIONS="pg_cron" setup_postgresql_db
|
||||
#
|
||||
# Variables:
|
||||
# PG_DB_NAME - Database name (required)
|
||||
@@ -6997,13 +6932,6 @@ function setup_postgresql_db() {
|
||||
$STD sudo -u postgres psql -c "CREATE ROLE $PG_DB_USER WITH LOGIN PASSWORD '$PG_DB_PASS';"
|
||||
$STD sudo -u postgres psql -c "CREATE DATABASE $PG_DB_NAME WITH OWNER $PG_DB_USER ENCODING 'UTF8' TEMPLATE template0;"
|
||||
|
||||
# Configure pg_cron database BEFORE creating the extension (must be set before pg_cron loads)
|
||||
if [[ -n "${PG_DB_EXTENSIONS:-}" ]] && [[ ",${PG_DB_EXTENSIONS//[[:space:]]/}," == *",pg_cron,"* ]]; then
|
||||
$STD sudo -u postgres psql -c "ALTER SYSTEM SET cron.database_name = '${PG_DB_NAME}';"
|
||||
$STD sudo -u postgres psql -c "ALTER SYSTEM SET cron.timezone = 'UTC';"
|
||||
$STD systemctl restart postgresql
|
||||
fi
|
||||
|
||||
# Install extensions (comma-separated)
|
||||
if [[ -n "${PG_DB_EXTENSIONS:-}" ]]; then
|
||||
IFS=',' read -ra EXT_LIST <<<"${PG_DB_EXTENSIONS:-}"
|
||||
@@ -7013,12 +6941,6 @@ function setup_postgresql_db() {
|
||||
done
|
||||
fi
|
||||
|
||||
# Grant pg_cron schema permissions to DB user
|
||||
if [[ -n "${PG_DB_EXTENSIONS:-}" ]] && [[ ",${PG_DB_EXTENSIONS//[[:space:]]/}," == *",pg_cron,"* ]]; then
|
||||
$STD sudo -u postgres psql -d "$PG_DB_NAME" -c "GRANT USAGE ON SCHEMA cron TO ${PG_DB_USER};"
|
||||
$STD sudo -u postgres psql -d "$PG_DB_NAME" -c "GRANT ALL ON ALL TABLES IN SCHEMA cron TO ${PG_DB_USER};"
|
||||
fi
|
||||
|
||||
# ALTER ROLE settings for Django/Rails compatibility (unless skipped)
|
||||
if [[ "${PG_DB_SKIP_ALTER_ROLE:-}" != "true" ]]; then
|
||||
$STD sudo -u postgres psql -c "ALTER ROLE $PG_DB_USER SET client_encoding TO 'utf8';"
|
||||
@@ -7060,6 +6982,7 @@ function setup_postgresql_db() {
|
||||
export PG_DB_USER
|
||||
export PG_DB_PASS
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Installs rbenv and ruby-build, installs Ruby and optionally Rails.
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user