mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-24 14:05:59 +01:00
Compare commits
1 Commits
main
...
feat/get-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a22baefdce |
341
.github/workflows/check-node-versions.yml
generated
vendored
341
.github/workflows/check-node-versions.yml
generated
vendored
@@ -1,341 +0,0 @@
|
||||
name: Check Node.js Version Drift
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Runs weekly on Monday at 06:00 UTC
|
||||
- cron: "0 6 * * 1"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
check-node-versions:
|
||||
if: github.repository == 'community-scripts/ProxmoxVE'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y -qq jq curl > /dev/null 2>&1
|
||||
|
||||
- name: Check upstream Node.js versions
|
||||
id: check
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
echo "================================================"
|
||||
echo " Checking Node.js version drift in install scripts"
|
||||
echo "================================================"
|
||||
|
||||
# Alpine version -> Node major cache (populated on demand)
|
||||
declare -A ALPINE_NODE_CACHE
|
||||
|
||||
# Resolve Node.js major version from Alpine package registry
|
||||
# Usage: resolve_alpine_node "3.21" => sets REPLY to major version (e.g. "22")
|
||||
resolve_alpine_node() {
|
||||
local alpine_ver="$1"
|
||||
if [[ -n "${ALPINE_NODE_CACHE[$alpine_ver]+x}" ]]; then
|
||||
REPLY="${ALPINE_NODE_CACHE[$alpine_ver]}"
|
||||
return
|
||||
fi
|
||||
|
||||
local url="https://pkgs.alpinelinux.org/package/v${alpine_ver}/main/x86_64/nodejs"
|
||||
local page
|
||||
page=$(curl -sf "$url" 2>/dev/null || echo "")
|
||||
local full_ver=""
|
||||
if [[ -n "$page" ]]; then
|
||||
# Parse: "Version | 24.13.0-r1" or similar table row
|
||||
full_ver=$(echo "$page" | grep -oP 'Version\s*\|\s*\K[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "")
|
||||
if [[ -z "$full_ver" ]]; then
|
||||
# Fallback: look for version pattern after "Version"
|
||||
full_ver=$(echo "$page" | grep -oP '(?<=Version</td><td>)[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "")
|
||||
fi
|
||||
fi
|
||||
|
||||
local major=""
|
||||
if [[ -n "$full_ver" ]]; then
|
||||
major="${full_ver%%.*}"
|
||||
fi
|
||||
|
||||
ALPINE_NODE_CACHE[$alpine_ver]="$major"
|
||||
REPLY="$major"
|
||||
}
|
||||
|
||||
# Extract Node major from a Dockerfile content
|
||||
# Sets: DF_NODE_MAJOR, DF_SOURCE (description of where we found it)
|
||||
extract_dockerfile_node() {
|
||||
local content="$1"
|
||||
DF_NODE_MAJOR=""
|
||||
DF_SOURCE=""
|
||||
|
||||
# 1) FROM node:XX (e.g. node:24-alpine, node:22.9.0-bookworm-slim, node:20)
|
||||
local node_from
|
||||
node_from=$(echo "$content" | grep -oP '(?i)FROM\s+(--platform=[^\s]+\s+)?node:\K[0-9]+' | head -1 || echo "")
|
||||
if [[ -n "$node_from" ]]; then
|
||||
DF_NODE_MAJOR="$node_from"
|
||||
DF_SOURCE="FROM node:${node_from}"
|
||||
return
|
||||
fi
|
||||
|
||||
# 2) nodesource/setup_XX.x
|
||||
local nodesource
|
||||
nodesource=$(echo "$content" | grep -oP 'nodesource/setup_\K[0-9]+' | head -1 || echo "")
|
||||
if [[ -n "$nodesource" ]]; then
|
||||
DF_NODE_MAJOR="$nodesource"
|
||||
DF_SOURCE="nodesource/setup_${nodesource}.x"
|
||||
return
|
||||
fi
|
||||
|
||||
# 3) FROM alpine:X.Y — resolve via Alpine packages
|
||||
local alpine_ver
|
||||
alpine_ver=$(echo "$content" | grep -oP '(?i)FROM\s+(--platform=[^\s]+\s+)?alpine:\K[0-9]+\.[0-9]+' | head -1 || echo "")
|
||||
if [[ -n "$alpine_ver" ]]; then
|
||||
resolve_alpine_node "$alpine_ver"
|
||||
if [[ -n "$REPLY" ]]; then
|
||||
DF_NODE_MAJOR="$REPLY"
|
||||
DF_SOURCE="alpine:${alpine_ver} (pkg: nodejs ${DF_NODE_MAJOR})"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Extract Node major from engines.node in package.json
|
||||
# Sets: ENGINES_NODE_RAW (raw string), ENGINES_MIN_MAJOR
|
||||
extract_engines_node() {
|
||||
local content="$1"
|
||||
ENGINES_NODE_RAW=""
|
||||
ENGINES_MIN_MAJOR=""
|
||||
|
||||
ENGINES_NODE_RAW=$(echo "$content" | jq -r '.engines.node // empty' 2>/dev/null || echo "")
|
||||
if [[ -z "$ENGINES_NODE_RAW" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Extract the first number (major) from the constraint
|
||||
# Handles: ">=24.13.1", "^22", ">=18.0.0", ">=18.15.0 <19 || ^20", etc.
|
||||
ENGINES_MIN_MAJOR=$(echo "$ENGINES_NODE_RAW" | grep -oP '\d+' | head -1 || echo "")
|
||||
}
|
||||
|
||||
# Collect results
|
||||
declare -a issue_scripts=()
|
||||
declare -a report_lines=()
|
||||
total=0
|
||||
checked=0
|
||||
drift_count=0
|
||||
|
||||
for script in install/*-install.sh; do
|
||||
[[ ! -f "$script" ]] && continue
|
||||
if ! grep -q 'setup_nodejs' "$script"; then
|
||||
continue
|
||||
fi
|
||||
|
||||
total=$((total + 1))
|
||||
slug=$(basename "$script" | sed 's/-install\.sh$//')
|
||||
|
||||
# Extract Source URL (GitHub only)
|
||||
source_url=$(head -20 "$script" | grep -oP '(?<=# Source: )https://github\.com/[^\s]+' | head -1 || echo "")
|
||||
if [[ -z "$source_url" ]]; then
|
||||
report_lines+=("| \`$slug\` | — | — | — | — | ⏭️ No GitHub source |")
|
||||
continue
|
||||
fi
|
||||
|
||||
repo=$(echo "$source_url" | sed -E 's|https://github\.com/||; s|/$||; s|\.git$||')
|
||||
if [[ -z "$repo" || "$repo" != */* ]]; then
|
||||
report_lines+=("| \`$slug\` | — | — | — | — | ⏭️ Invalid repo |")
|
||||
continue
|
||||
fi
|
||||
|
||||
checked=$((checked + 1))
|
||||
|
||||
# Extract our NODE_VERSION
|
||||
our_version=$(grep -oP 'NODE_VERSION="(\d+)"' "$script" | head -1 | grep -oP '\d+' || echo "")
|
||||
if [[ -z "$our_version" ]]; then
|
||||
if grep -q 'NODE_VERSION=\$(' "$script"; then
|
||||
our_version="dynamic"
|
||||
else
|
||||
our_version="unset"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fetch upstream Dockerfile
|
||||
df_content=""
|
||||
for branch in main master dev; do
|
||||
df_content=$(curl -sf "https://raw.githubusercontent.com/${repo}/${branch}/Dockerfile" 2>/dev/null || echo "")
|
||||
[[ -n "$df_content" ]] && break
|
||||
done
|
||||
|
||||
DF_NODE_MAJOR=""
|
||||
DF_SOURCE=""
|
||||
if [[ -n "$df_content" ]]; then
|
||||
extract_dockerfile_node "$df_content"
|
||||
fi
|
||||
|
||||
# Fetch upstream package.json
|
||||
pkg_content=""
|
||||
for branch in main master dev; do
|
||||
pkg_content=$(curl -sf "https://raw.githubusercontent.com/${repo}/${branch}/package.json" 2>/dev/null || echo "")
|
||||
[[ -n "$pkg_content" ]] && break
|
||||
done
|
||||
|
||||
ENGINES_NODE_RAW=""
|
||||
ENGINES_MIN_MAJOR=""
|
||||
if [[ -n "$pkg_content" ]]; then
|
||||
extract_engines_node "$pkg_content"
|
||||
fi
|
||||
|
||||
# Determine upstream recommended major version
|
||||
upstream_major=""
|
||||
upstream_hint=""
|
||||
|
||||
if [[ -n "$DF_NODE_MAJOR" ]]; then
|
||||
upstream_major="$DF_NODE_MAJOR"
|
||||
upstream_hint="$DF_SOURCE"
|
||||
elif [[ -n "$ENGINES_MIN_MAJOR" ]]; then
|
||||
upstream_major="$ENGINES_MIN_MAJOR"
|
||||
upstream_hint="engines: $ENGINES_NODE_RAW"
|
||||
fi
|
||||
|
||||
# Build display values
|
||||
engines_display="${ENGINES_NODE_RAW:-—}"
|
||||
dockerfile_display="${DF_SOURCE:-—}"
|
||||
|
||||
# Compare
|
||||
status="✅"
|
||||
if [[ "$our_version" == "dynamic" ]]; then
|
||||
status="🔄 Dynamic"
|
||||
elif [[ "$our_version" == "unset" ]]; then
|
||||
status="⚠️ NODE_VERSION not set"
|
||||
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
||||
drift_count=$((drift_count + 1))
|
||||
elif [[ -n "$upstream_major" && "$our_version" != "$upstream_major" ]]; then
|
||||
status="🔸 Drift → upstream=$upstream_major ($upstream_hint)"
|
||||
issue_scripts+=("$slug|$our_version|$upstream_major|$upstream_hint|$repo")
|
||||
drift_count=$((drift_count + 1))
|
||||
fi
|
||||
|
||||
report_lines+=("| \`$slug\` | $our_version | $engines_display | $dockerfile_display | [$repo](https://github.com/$repo) | $status |")
|
||||
|
||||
# Rate-limit to avoid GitHub secondary rate limits
|
||||
sleep 0.3
|
||||
|
||||
done
|
||||
|
||||
# Print summary
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo " Total scripts with setup_nodejs: $total"
|
||||
echo " Checked (with GitHub source): $checked"
|
||||
echo " Version drift detected: $drift_count"
|
||||
echo "========================================="
|
||||
|
||||
# Export
|
||||
{
|
||||
echo "drift_count=$drift_count"
|
||||
echo "total=$total"
|
||||
echo "checked=$checked"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Save issue details for next step
|
||||
printf '%s\n' "${issue_scripts[@]}" > /tmp/drift_scripts.txt 2>/dev/null || touch /tmp/drift_scripts.txt
|
||||
|
||||
# Save full report
|
||||
{
|
||||
echo "## Node.js Version Drift Report"
|
||||
echo ""
|
||||
echo "**Generated:** $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
echo "**Scripts checked:** $total | **With GitHub source:** $checked | **Drift detected:** $drift_count"
|
||||
echo ""
|
||||
echo "| Script | Our Version | engines.node | Dockerfile | Upstream Repo | Status |"
|
||||
echo "|--------|-------------|-------------|------------|---------------|--------|"
|
||||
printf '%s\n' "${report_lines[@]}" | sort
|
||||
} > /tmp/drift_report.md
|
||||
|
||||
cat /tmp/drift_report.md
|
||||
|
||||
- name: Create or update summary issue
|
||||
if: steps.check.outputs.drift_count != '0'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
TITLE="[Automated] Node.js Version Drift Report"
|
||||
DATE=$(date -u +%Y-%m-%d)
|
||||
DRIFT_COUNT="${{ steps.check.outputs.drift_count }}"
|
||||
TOTAL="${{ steps.check.outputs.total }}"
|
||||
CHECKED="${{ steps.check.outputs.checked }}"
|
||||
|
||||
# Build checklist from drift data
|
||||
CHECKLIST=""
|
||||
while IFS='|' read -r slug our_version upstream_major upstream_hint repo; do
|
||||
[[ -z "$slug" ]] && continue
|
||||
CHECKLIST+="- [ ] **\`${slug}\`** — ours: \`${our_version}\` → upstream: \`${upstream_major}\` (${upstream_hint}) — [repo](https://github.com/${repo})"$'\n'
|
||||
done < /tmp/drift_scripts.txt
|
||||
|
||||
# Build full report table
|
||||
REPORT=$(cat /tmp/drift_report.md)
|
||||
|
||||
BODY=$(cat <<ISSUE_EOF
|
||||
## Node.js Version Drift Report — ${DATE}
|
||||
|
||||
**${DRIFT_COUNT}** script(s) with version drift detected (out of ${CHECKED} checked / ${TOTAL} total).
|
||||
|
||||
### Scripts requiring investigation
|
||||
|
||||
${CHECKLIST}
|
||||
|
||||
### How to resolve
|
||||
|
||||
1. Check upstream Dockerfile / package.json to confirm the required Node.js version
|
||||
2. Test the script with the new Node version
|
||||
3. Update \`NODE_VERSION\` in \`install/<slug>-install.sh\`
|
||||
4. Update \`NODE_VERSION\` in \`ct/<slug>.sh\` (update section) if applicable
|
||||
5. Check off the item above once done
|
||||
|
||||
<details>
|
||||
<summary>Full report</summary>
|
||||
|
||||
${REPORT}
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
*This issue is automatically created/updated weekly by the Node.js version drift check workflow.*
|
||||
*Last updated: ${DATE}*
|
||||
ISSUE_EOF
|
||||
)
|
||||
|
||||
# Check if a matching open issue already exists
|
||||
EXISTING=$(gh issue list --state open --label "automated,dependencies" --search "\"[Automated] Node.js Version Drift Report\"" --json number --jq '.[0].number // empty' 2>/dev/null || echo "")
|
||||
|
||||
if [[ -n "$EXISTING" ]]; then
|
||||
gh issue edit "$EXISTING" --body "$BODY"
|
||||
echo "Updated existing issue #$EXISTING"
|
||||
else
|
||||
gh issue create \
|
||||
--title "$TITLE" \
|
||||
--body "$BODY" \
|
||||
--label "automated,dependencies"
|
||||
echo "Created new summary issue"
|
||||
fi
|
||||
|
||||
- name: Close issue if no drift
|
||||
if: steps.check.outputs.drift_count == '0'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
EXISTING=$(gh issue list --state open --label "automated,dependencies" --search "\"[Automated] Node.js Version Drift Report\"" --json number --jq '.[0].number // empty' 2>/dev/null || echo "")
|
||||
if [[ -n "$EXISTING" ]]; then
|
||||
gh issue close "$EXISTING" --comment "All Node.js versions are in sync with upstream. Closing automatically."
|
||||
echo "Closed issue #$EXISTING"
|
||||
fi
|
||||
111
.github/workflows/stale_pr_close.yml
generated
vendored
111
.github/workflows/stale_pr_close.yml
generated
vendored
@@ -1,111 +0,0 @@
|
||||
name: Stale PR Management
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
stale-prs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Handle stale PRs
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const now = new Date();
|
||||
const owner = context.repo.owner;
|
||||
const repo = context.repo.repo;
|
||||
|
||||
// --- When stale label is added, comment immediately ---
|
||||
if (context.eventName === "pull_request_target" && context.payload.action === "labeled") {
|
||||
const label = context.payload.label?.name;
|
||||
if (label === "stale") {
|
||||
const author = context.payload.pull_request.user.login;
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
body: `@${author} This PR has been marked as stale. It will be closed if no new commits are added in 7 days.`
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Scheduled run: check all stale PRs ---
|
||||
const { data: prs } = await github.rest.pulls.list({
|
||||
owner,
|
||||
repo,
|
||||
state: "open",
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
for (const pr of prs) {
|
||||
const hasStale = pr.labels.some(l => l.name === "stale");
|
||||
if (!hasStale) continue;
|
||||
|
||||
// Get timeline events to find when stale label was added
|
||||
const { data: events } = await github.rest.issues.listEvents({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
// Find the most recent time the stale label was added
|
||||
const staleLabelEvents = events
|
||||
.filter(e => e.event === "labeled" && e.label?.name === "stale")
|
||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
|
||||
|
||||
if (staleLabelEvents.length === 0) continue;
|
||||
|
||||
const staleLabelDate = new Date(staleLabelEvents[0].created_at);
|
||||
const daysSinceStale = (now - staleLabelDate) / (1000 * 60 * 60 * 24);
|
||||
|
||||
// Check for new commits since stale label was added
|
||||
const { data: commits } = await github.rest.pulls.listCommits({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pr.number
|
||||
});
|
||||
|
||||
const lastCommitDate = new Date(commits[commits.length - 1].commit.author.date);
|
||||
const author = pr.user.login;
|
||||
|
||||
// If there are new commits after the stale label, remove it
|
||||
if (lastCommitDate > staleLabelDate) {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
name: "stale"
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
body: `@${author} Recent activity detected. Removing stale label.`
|
||||
});
|
||||
}
|
||||
// If 7 days have passed since stale label, close the PR
|
||||
else if (daysSinceStale > 7) {
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pr.number,
|
||||
state: "closed"
|
||||
});
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: pr.number,
|
||||
body: `@${author} Closing stale PR due to inactivity (no commits for 7 days after stale label).`
|
||||
});
|
||||
}
|
||||
}
|
||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -415,32 +415,12 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Refactor n8n [@MickLesk](https://github.com/MickLesk) ([#12264](https://github.com/community-scripts/ProxmoxVE/pull/12264))
|
||||
- Firefly: PHP bump [@tremor021](https://github.com/tremor021) ([#12247](https://github.com/community-scripts/ProxmoxVE/pull/12247))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- make searxng updateable [@shtefko](https://github.com/shtefko) ([#12207](https://github.com/community-scripts/ProxmoxVE/pull/12207))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- bump various scripts from Node 22 to 24 [@MickLesk](https://github.com/MickLesk) ([#12265](https://github.com/community-scripts/ProxmoxVE/pull/12265))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func: add get_latest_gh_tag helper function [@MickLesk](https://github.com/MickLesk) ([#12261](https://github.com/community-scripts/ProxmoxVE/pull/12261))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- Arcane ([#12263](https://github.com/community-scripts/ProxmoxVE/pull/12263))
|
||||
|
||||
### 📂 Github
|
||||
|
||||
- github: add weekly Node.js version drift check workflow [@MickLesk](https://github.com/MickLesk) ([#12267](https://github.com/community-scripts/ProxmoxVE/pull/12267))
|
||||
- add: workflow to close stale PRs [@CrazyWolf13](https://github.com/CrazyWolf13) ([#12243](https://github.com/community-scripts/ProxmoxVE/pull/12243))
|
||||
|
||||
## 2026-02-23
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
@@ -20,28 +20,26 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
if command -v cross-seed &>/dev/null; then
|
||||
current_version=$(cross-seed --version)
|
||||
latest_version=$(npm show cross-seed version)
|
||||
if [ "$current_version" != "$latest_version" ]; then
|
||||
msg_info "Updating cross-seed from version v${current_version} to v${latest_version}"
|
||||
$STD npm install -g cross-seed@latest
|
||||
systemctl restart cross-seed
|
||||
msg_ok "Updated successfully!"
|
||||
if command -v cross-seed &>/dev/null; then
|
||||
current_version=$(cross-seed --version)
|
||||
latest_version=$(npm show cross-seed version)
|
||||
if [ "$current_version" != "$latest_version" ]; then
|
||||
msg_info "Updating cross-seed from version v${current_version} to v${latest_version}"
|
||||
$STD npm install -g cross-seed@latest
|
||||
systemctl restart cross-seed
|
||||
msg_ok "Updated successfully!"
|
||||
else
|
||||
msg_ok "cross-seed is already at v${current_version}"
|
||||
fi
|
||||
else
|
||||
msg_ok "cross-seed is already at v${current_version}"
|
||||
msg_error "No cross-seed Installation Found!"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
msg_error "No cross-seed Installation Found!"
|
||||
exit
|
||||
fi
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
|
||||
@@ -28,8 +28,6 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
|
||||
|
||||
if check_for_gh_release "manyfold" "manyfold3d/manyfold"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop manyfold.target manyfold-rails.1 manyfold-default_worker.1 manyfold-performance_worker.1
|
||||
|
||||
@@ -29,7 +29,7 @@ function update_script() {
|
||||
fi
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
NODE_VERSION="24" NODE_MODULE="matterbridge" setup_nodejs
|
||||
NODE_VERSION="22" NODE_MODULE="matterbridge" setup_nodejs
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
14
ct/n8n.sh
14
ct/n8n.sh
@@ -27,11 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
ensure_dependencies graphicsmagick
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
msg_info "Updating n8n"
|
||||
ensure_dependencies graphicsmagick
|
||||
if [ ! -f /opt/n8n.env ]; then
|
||||
sed -i 's|^Environment="N8N_SECURE_COOKIE=false"$|EnvironmentFile=/opt/n8n.env|' /etc/systemd/system/n8n.service
|
||||
mkdir -p /opt
|
||||
@@ -41,12 +37,14 @@ N8N_PORT=5678
|
||||
N8N_PROTOCOL=http
|
||||
N8N_HOST=$LOCAL_IP
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
|
||||
$STD npm update -g n8n
|
||||
msg_info "Updating ${APP} LXC"
|
||||
rm -rf /usr/lib/node_modules/.n8n-* /usr/lib/node_modules/n8n
|
||||
$STD npm install -g n8n --force
|
||||
systemctl restart n8n
|
||||
msg_ok "Updated n8n"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
if check_for_gh_release "pangolin" "fosrl/pangolin"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop pangolin
|
||||
|
||||
82
ct/romm.sh
82
ct/romm.sh
@@ -20,50 +20,48 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -d /opt/romm ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
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
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
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
|
||||
|
||||
@@ -28,8 +28,6 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
if check_for_gh_release "snowshare" "TuroYT/snowshare"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop snowshare
|
||||
|
||||
@@ -33,7 +33,7 @@ function update_script() {
|
||||
$STD apt upgrade -y
|
||||
msg_ok "Updated LXC Container"
|
||||
|
||||
NODE_VERSION="24" NODE_MODULE="verdaccio" setup_nodejs
|
||||
NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
|
||||
systemctl restart verdaccio
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "Arcane",
|
||||
"slug": "arcane",
|
||||
"categories": [
|
||||
3
|
||||
],
|
||||
"date_created": "2026-02-24",
|
||||
"type": "addon",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 3552,
|
||||
"documentation": "https://getarcane.app/docs",
|
||||
"website": "https://getarcane.app/",
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/arcane.webp",
|
||||
"config_path": "/opt/arcane/.env",
|
||||
"description": "Arcane is designed to be an easy and modern Docker management platform, built with everybody in mind. The goal of Arcane is to be built for and by the community to make sure nobody feels left out or behind with their specific features or processes. ",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "tools/addon/arcane.sh",
|
||||
"resources": {
|
||||
"cpu": null,
|
||||
"ram": null,
|
||||
"hdd": null,
|
||||
"os": null,
|
||||
"version": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": "arcane",
|
||||
"password": "arcane-admin"
|
||||
},
|
||||
"notes": [
|
||||
{
|
||||
"text": "This is an addon script intended to be used on top of an existing Docker container.",
|
||||
"type": "info"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-02-24T12:15:44Z",
|
||||
"generated": "2026-02-24T06:23:39Z",
|
||||
"versions": [
|
||||
{
|
||||
"slug": "2fauth",
|
||||
@@ -606,9 +606,9 @@
|
||||
{
|
||||
"slug": "invoiceninja",
|
||||
"repo": "invoiceninja/invoiceninja",
|
||||
"version": "v5.12.66",
|
||||
"version": "v5.12.65",
|
||||
"pinned": false,
|
||||
"date": "2026-02-24T09:12:50Z"
|
||||
"date": "2026-02-21T01:03:52Z"
|
||||
},
|
||||
{
|
||||
"slug": "jackett",
|
||||
@@ -1679,7 +1679,7 @@
|
||||
"repo": "meilisearch/meilisearch",
|
||||
"version": "v1.36.0",
|
||||
"pinned": false,
|
||||
"date": ""
|
||||
"date": "2026-02-23T08:13:32Z"
|
||||
},
|
||||
{
|
||||
"slug": "warracker",
|
||||
|
||||
@@ -13,7 +13,7 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
|
||||
msg_info "Setup Cross-Seed"
|
||||
$STD npm install cross-seed@latest -g
|
||||
|
||||
@@ -26,7 +26,7 @@ msg_ok "Installed Dependencies"
|
||||
setup_imagemagick
|
||||
PG_VERSION="16" setup_postgresql
|
||||
PG_DB_NAME="manyfold" PG_DB_USER="manyfold" setup_postgresql_db
|
||||
NODE_VERSION="24" NODE_MODULE="yarn" setup_nodejs
|
||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||
|
||||
fetch_and_deploy_gh_release "manyfold" "manyfold3d/manyfold" "tarball" "latest" "/opt/manyfold/app"
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ update_os
|
||||
|
||||
msg_info "Install Matterbridge"
|
||||
mkdir -p /root/Matterbridge
|
||||
NODE_VERSION="24" NODE_MODULE="matterbridge" setup_nodejs
|
||||
NODE_VERSION="22" NODE_MODULE="matterbridge" setup_nodejs
|
||||
msg_ok "Installed Matterbridge"
|
||||
|
||||
msg_info "Creating Service"
|
||||
|
||||
@@ -15,19 +15,22 @@ update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y \
|
||||
ca-certificates \
|
||||
build-essential \
|
||||
python3 \
|
||||
python3-setuptools \
|
||||
graphicsmagick
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
|
||||
msg_info "Installing n8n (Patience)"
|
||||
$STD npm install -g n8n
|
||||
$STD npm install --global patch-package
|
||||
$STD npm install --global n8n
|
||||
msg_ok "Installed n8n"
|
||||
|
||||
msg_info "Creating Service"
|
||||
mkdir -p /opt
|
||||
cat <<EOF >/opt/n8n.env
|
||||
N8N_SECURE_COOKIE=false
|
||||
N8N_PORT=5678
|
||||
|
||||
@@ -14,7 +14,7 @@ network_check
|
||||
update_os
|
||||
|
||||
fetch_and_deploy_gh_release "nodecast-tv" "technomancer702/nodecast-tv"
|
||||
NODE_VERSION="20" setup_nodejs
|
||||
setup_nodejs
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y ffmpeg
|
||||
|
||||
@@ -19,7 +19,7 @@ $STD apt install -y \
|
||||
iptables
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball"
|
||||
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64"
|
||||
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_amd64.tar.gz"
|
||||
|
||||
@@ -42,7 +42,7 @@ $STD apt install -y \
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
PYTHON_VERSION="3.13" setup_uv
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
setup_mariadb
|
||||
MARIADB_DB_NAME="romm" MARIADB_DB_USER="romm" setup_mariadb_db
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
PG_VERSION="17" setup_postgresql
|
||||
PG_DB_USER="snowshare" PG_DB_NAME="snowshare" setup_postgresql_db
|
||||
fetch_and_deploy_gh_release "snowshare" "TuroYT/snowshare" "tarball"
|
||||
|
||||
@@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
|
||||
$STD apt install -y build-essential
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="24" NODE_MODULE="verdaccio" setup_nodejs
|
||||
NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
|
||||
|
||||
msg_info "Configuring Verdaccio"
|
||||
mkdir -p /opt/verdaccio/config
|
||||
|
||||
@@ -23,7 +23,7 @@ $STD apt install -y \
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
setup_rust
|
||||
NODE_VERSION="20" NODE_MODULE="pnpm" setup_nodejs
|
||||
NODE_MODULE="pnpm" setup_nodejs
|
||||
fetch_and_deploy_gh_release "wealthfolio" "afadil/wealthfolio" "tarball"
|
||||
|
||||
msg_info "Building Frontend (patience)"
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: summoningpixels
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/getarcaneapp/arcane
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================
|
||||
APP="Arcane"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/arcane"
|
||||
COMPOSE_FILE="${INSTALL_PATH}/compose.yaml"
|
||||
ENV_FILE="${INSTALL_PATH}/.env"
|
||||
DEFAULT_PORT=3552
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ ____ _________ _ ________
|
||||
/ | / __ \/ ____/ | / | / / ____/
|
||||
/ /| | / /_/ / / / /| | / |/ / __/
|
||||
/ ___ |/ _, _/ /___/ ___ |/ /| / /___
|
||||
/_/ |_/_/ |_|\____/_/ |_/_/ |_/_____/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
msg_info "Stopping and removing Docker containers"
|
||||
cd "$INSTALL_PATH"
|
||||
$STD docker compose down --volumes --remove-orphans
|
||||
msg_ok "Stopped and removed Docker containers"
|
||||
fi
|
||||
|
||||
rm -rf "$INSTALL_PATH"
|
||||
rm -f "/usr/local/bin/update_arcane"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
msg_info "Pulling latest ${APP} image"
|
||||
cd "$INSTALL_PATH"
|
||||
$STD docker compose pull
|
||||
msg_ok "Pulled latest image"
|
||||
|
||||
msg_info "Restarting ${APP}"
|
||||
$STD docker compose up -d --remove-orphans
|
||||
msg_ok "Restarted ${APP}"
|
||||
|
||||
msg_ok "Updated successfully"
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK DOCKER
|
||||
# ==============================================================================
|
||||
function check_docker() {
|
||||
if ! command -v docker &>/dev/null; then
|
||||
msg_error "Docker is not installed. This script requires an existing Docker LXC. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
if ! docker compose version &>/dev/null; then
|
||||
msg_error "Docker Compose plugin is not available. Please install it before running this script. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_docker
|
||||
|
||||
msg_info "Creating install directory"
|
||||
mkdir -p "$INSTALL_PATH"
|
||||
msg_ok "Created ${INSTALL_PATH}"
|
||||
|
||||
# Generate secrets and config values
|
||||
local ENCRYPTION_KEY JWT_SECRET PROJ_DIR
|
||||
ENCRYPTION_KEY=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
|
||||
JWT_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c32)
|
||||
PROJ_DIR="/etc/arcane/projects"
|
||||
|
||||
msg_info "Creating stacks directory"
|
||||
mkdir -p "$PROJ_DIR"
|
||||
msg_ok "Created ${PROJ_DIR}"
|
||||
|
||||
msg_info "Downloading Docker Compose file"
|
||||
curl -fsSL "https://raw.githubusercontent.com/getarcaneapp/arcane/refs/heads/main/docker/examples/compose.basic.yaml" -o "$COMPOSE_FILE"
|
||||
msg_ok "Downloaded Docker Compose file"
|
||||
|
||||
msg_info "Downloading .env file"
|
||||
curl -fsSL "https://raw.githubusercontent.com/getarcaneapp/arcane/refs/heads/main/.env.example" -o "$ENV_FILE"
|
||||
chmod 600 "$ENV_FILE"
|
||||
msg_ok "Downloaded .env file"
|
||||
|
||||
msg_info "Configuring compose and env files"
|
||||
sed -i '/^[[:space:]]*#/!s|/host/path/to/projects|'"$PROJ_DIR"'|g' "$COMPOSE_FILE"
|
||||
sed -i '/^[[:space:]]*#/!s|ENCRYPTION_KEY=.*|ENCRYPTION_KEY='"$ENCRYPTION_KEY"'|g' "$COMPOSE_FILE"
|
||||
sed -i '/^[[:space:]]*#/!s|JWT_SECRET=.*|JWT_SECRET='"$JWT_SECRET"'|g' "$COMPOSE_FILE"
|
||||
sed -i '/^[[:space:]]*#/!s|APP_URL=.*|APP_URL=http://localhost:'"$DEFAULT_PORT"'|g' "$ENV_FILE"
|
||||
sed -i '/^[[:space:]]*#/!s|ENCRYPTION_KEY=.*|#&|g' "$ENV_FILE"
|
||||
sed -i '/^[[:space:]]*#/!s|JWT_SECRET=.*|#&|g' "$ENV_FILE"
|
||||
msg_ok "Configured compose and env files"
|
||||
|
||||
msg_info "Starting ${APP}"
|
||||
cd "$INSTALL_PATH"
|
||||
$STD docker compose up -d
|
||||
msg_ok "Started ${APP}"
|
||||
|
||||
# Create update script
|
||||
msg_info "Creating update script"
|
||||
cat <<'UPDATEEOF' >/usr/local/bin/update_arcane
|
||||
#!/usr/bin/env bash
|
||||
# Arcane Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/arcane.sh)"
|
||||
UPDATEEOF
|
||||
chmod +x /usr/local/bin/update_arcane
|
||||
msg_ok "Created update script (/usr/local/bin/update_arcane)"
|
||||
|
||||
echo ""
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
|
||||
echo ""
|
||||
echo -e "Arcane Credentials"
|
||||
echo -e "=================="
|
||||
echo -e "User: arcane"
|
||||
echo -e "Password: arcane-admin"
|
||||
echo ""
|
||||
msg_warn "On first access, you'll be prompted to change your password."
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
header_info
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo ""
|
||||
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
uninstall
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_warn "No action selected. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Fresh installation
|
||||
msg_warn "${APP} is not installed."
|
||||
echo ""
|
||||
echo -e "${TAB}${INFO} This will install:"
|
||||
echo -e "${TAB} - Arcane (via Docker Compose)"
|
||||
echo ""
|
||||
|
||||
echo -n "${TAB}Install ${APP}? (y/N): "
|
||||
read -r install_prompt
|
||||
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
install
|
||||
else
|
||||
msg_warn "Installation cancelled. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
@@ -1,6 +0,0 @@
|
||||
___
|
||||
/ | ______________ _____ ___
|
||||
/ /| | / ___/ ___/ __ `/ __ \/ _ \
|
||||
/ ___ |/ / / /__/ /_/ / / / / __/
|
||||
/_/ |_/_/ \___/\__,_/_/ /_/\___/
|
||||
|
||||
Reference in New Issue
Block a user