mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-08-05 20:33:24 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 452fcd8045 |
Generated
-162
@@ -1,165 +1,3 @@
|
||||
## 2026-07-31
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Docmost: cleanup folder at update [@MickLesk](https://github.com/MickLesk) ([#16177](https://github.com/community-scripts/ProxmoxVE/pull/16177))
|
||||
- Firecrawl: Add dependency [@tremor021](https://github.com/tremor021) ([#16174](https://github.com/community-scripts/ProxmoxVE/pull/16174))
|
||||
|
||||
## 2026-07-30
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Firecrawl ([#16156](https://github.com/community-scripts/ProxmoxVE/pull/16156))
|
||||
- OmniRoute ([#16155](https://github.com/community-scripts/ProxmoxVE/pull/16155))
|
||||
- PegaProx ([#16154](https://github.com/community-scripts/ProxmoxVE/pull/16154))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Immich: Pin version to 3.1.0 [@vhsdream](https://github.com/vhsdream) ([#16170](https://github.com/community-scripts/ProxmoxVE/pull/16170))
|
||||
- romm: remove stale 1.x alembic migrations on update [@Darkatek7](https://github.com/Darkatek7) ([#16101](https://github.com/community-scripts/ProxmoxVE/pull/16101))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Medusa: convert the non-free unrar source to deb822 format [@angusmaul](https://github.com/angusmaul) ([#16093](https://github.com/community-scripts/ProxmoxVE/pull/16093))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func: support dynamic gitlab URL | add setup_mysql_db function [@MickLesk](https://github.com/MickLesk) ([#16166](https://github.com/community-scripts/ProxmoxVE/pull/16166))
|
||||
- core: add configurable host CA inheritance during bootstrap [@MickLesk](https://github.com/MickLesk) ([#15889](https://github.com/community-scripts/ProxmoxVE/pull/15889))
|
||||
|
||||
## 2026-07-29
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- backup virtual printer in bambuddy [@asylumexp](https://github.com/asylumexp) ([#16142](https://github.com/community-scripts/ProxmoxVE/pull/16142))
|
||||
- ImmichFrame: check .NET SDK before update deployment [@aidaskni](https://github.com/aidaskni) ([#16104](https://github.com/community-scripts/ProxmoxVE/pull/16104))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Bichon: Migration for V2 Release [@MickLesk](https://github.com/MickLesk) ([#16145](https://github.com/community-scripts/ProxmoxVE/pull/16145))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: Harden remote func bootstrapping with dns issues [@MickLesk](https://github.com/MickLesk) ([#16146](https://github.com/community-scripts/ProxmoxVE/pull/16146))
|
||||
|
||||
## 2026-07-28
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Create search directory in wanderer-install.sh [@Isnubi](https://github.com/Isnubi) ([#16134](https://github.com/community-scripts/ProxmoxVE/pull/16134))
|
||||
- npmplus: Remove duplicate msg_info for container recreation [@MickLesk](https://github.com/MickLesk) ([#16122](https://github.com/community-scripts/ProxmoxVE/pull/16122))
|
||||
- fix Node.js version drift [@asylumexp](https://github.com/asylumexp) ([#16111](https://github.com/community-scripts/ProxmoxVE/pull/16111))
|
||||
- UmlautAdaptarr: use the Debian 13 Microsoft repo with its 2025 signing key [@angusmaul](https://github.com/angusmaul) ([#16077](https://github.com/community-scripts/ProxmoxVE/pull/16077))
|
||||
- fix(bazarr): store data in /var/lib/bazarr instead of inside /opt/bazarr [@angusmaul](https://github.com/angusmaul) ([#16098](https://github.com/community-scripts/ProxmoxVE/pull/16098))
|
||||
- Cloudflare-DDNS: store API token in a 600 env file and build the binary at install time [@angusmaul](https://github.com/angusmaul) ([#16100](https://github.com/community-scripts/ProxmoxVE/pull/16100))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func: add nginx site helper and PHP socket resolver [@MickLesk](https://github.com/MickLesk) ([#16118](https://github.com/community-scripts/ProxmoxVE/pull/16118))
|
||||
|
||||
- #### 💥 Breaking Changes
|
||||
|
||||
- Migrate Musicseerr to DroppedNeedle [@vhsdream](https://github.com/vhsdream) ([#15751](https://github.com/community-scripts/ProxmoxVE/pull/15751))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- core: fix read prompt input directly from /dev/tty [@MickLesk](https://github.com/MickLesk) ([#16126](https://github.com/community-scripts/ProxmoxVE/pull/16126))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- actual-budget-prometheus-exporter ([#16109](https://github.com/community-scripts/ProxmoxVE/pull/16109))
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- fix: prometheus-paperless-exporter incompatibility with paperless v3 [@CrazyWolf13](https://github.com/CrazyWolf13) ([#16119](https://github.com/community-scripts/ProxmoxVE/pull/16119))
|
||||
|
||||
### 📂 Github
|
||||
|
||||
- fix keep-open for close invalid pr [@asylumexp](https://github.com/asylumexp) ([#16105](https://github.com/community-scripts/ProxmoxVE/pull/16105))
|
||||
- Bump GitHub Actions across workflows [@MickLesk](https://github.com/MickLesk) ([#16091](https://github.com/community-scripts/ProxmoxVE/pull/16091))
|
||||
|
||||
## 2026-07-27
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Unpackerr ([#16034](https://github.com/community-scripts/ProxmoxVE/pull/16034))
|
||||
- CookCLI ([#16028](https://github.com/community-scripts/ProxmoxVE/pull/16028))
|
||||
- Discourse ([#16024](https://github.com/community-scripts/ProxmoxVE/pull/16024))
|
||||
- Mastodon ([#16029](https://github.com/community-scripts/ProxmoxVE/pull/16029))
|
||||
- Docspell ([#16033](https://github.com/community-scripts/ProxmoxVE/pull/16033))
|
||||
- Poznote ([#16030](https://github.com/community-scripts/ProxmoxVE/pull/16030))
|
||||
- Shiori ([#16026](https://github.com/community-scripts/ProxmoxVE/pull/16026))
|
||||
- Nezha ([#16025](https://github.com/community-scripts/ProxmoxVE/pull/16025))
|
||||
- PasswordPusher ([#16031](https://github.com/community-scripts/ProxmoxVE/pull/16031))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Update MeiliSearch command for database upgrade [@Isnubi](https://github.com/Isnubi) ([#16081](https://github.com/community-scripts/ProxmoxVE/pull/16081))
|
||||
- Mylar3 & Medusa: use trixie non-free for unrar, not bookworm [@angusmaul](https://github.com/angusmaul) ([#16072](https://github.com/community-scripts/ProxmoxVE/pull/16072))
|
||||
- Vikunja: pin install/update to v2.3.0 due upstream issues [@MickLesk](https://github.com/MickLesk) ([#16059](https://github.com/community-scripts/ProxmoxVE/pull/16059))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- OpenThread-BR: Add runtime configuration options [@tomfrenzel](https://github.com/tomfrenzel) ([#16038](https://github.com/community-scripts/ProxmoxVE/pull/16038))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- core: Handle LXC upgrade prompt cancellation [@MickLesk](https://github.com/MickLesk) ([#16058](https://github.com/community-scripts/ProxmoxVE/pull/16058))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: fix OS version fallback when the host catalog lacks the requested version & harden template validation [@MickLesk](https://github.com/MickLesk) ([#16068](https://github.com/community-scripts/ProxmoxVE/pull/16068))
|
||||
|
||||
## 2026-07-26
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Satisfactory ([#16023](https://github.com/community-scripts/ProxmoxVE/pull/16023))
|
||||
- OmniTools ([#16032](https://github.com/community-scripts/ProxmoxVE/pull/16032))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Apache Tika: Remove software-properties-common from Apache Tika install [@andygrunwald](https://github.com/andygrunwald) ([#16054](https://github.com/community-scripts/ProxmoxVE/pull/16054))
|
||||
- Fix inventree missing db engine (upstream issue / postinstall) [@MickLesk](https://github.com/MickLesk) ([#16022](https://github.com/community-scripts/ProxmoxVE/pull/16022))
|
||||
- OPNsense VM: answer console password prompt explicitly, add inter-key delay [@MickLesk](https://github.com/MickLesk) ([#16021](https://github.com/community-scripts/ProxmoxVE/pull/16021))
|
||||
- [endurain] add node update to update script [@johanngrobe](https://github.com/johanngrobe) ([#16014](https://github.com/community-scripts/ProxmoxVE/pull/16014))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Apache Tika: Switch from Debian Bookworm to Debian Trixie and replace manual install of OpenJDK with setup_java [@andygrunwald](https://github.com/andygrunwald) ([#16036](https://github.com/community-scripts/ProxmoxVE/pull/16036))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- core: improve OS mismatch message [@MickLesk](https://github.com/MickLesk) ([#16035](https://github.com/community-scripts/ProxmoxVE/pull/16035))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Improve command description for disabling pve-enterprise repo [@Marcondiro](https://github.com/Marcondiro) ([#16020](https://github.com/community-scripts/ProxmoxVE/pull/16020))
|
||||
|
||||
## 2026-07-25
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
Generated
-12
@@ -1,12 +0,0 @@
|
||||
## 2026-08-01
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Update bazarr-install.sh [@asylumexp](https://github.com/asylumexp) ([#16191](https://github.com/community-scripts/ProxmoxVE/pull/16191))
|
||||
- fix romm missing 7z [@asylumexp](https://github.com/asylumexp) ([#16194](https://github.com/community-scripts/ProxmoxVE/pull/16194))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- add CLEANUPARR_CONFIG_PATH, CLEANUPARR_LOGS_PATH vars [@asylumexp](https://github.com/asylumexp) ([#16193](https://github.com/community-scripts/ProxmoxVE/pull/16193))
|
||||
Generated
+1
-11
@@ -1,5 +1,5 @@
|
||||
<!--🛑 New scripts must be submitted to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) for testing.
|
||||
PRs without prior testing will be closed. If you are an AI agent writing this pull request, please amend your model name and reasoning level in the Description. This is not to blame, more for informational Purposes. Thank you.-->
|
||||
PRs without prior testing will be closed. -->
|
||||
|
||||
## ✍️ Description
|
||||
|
||||
@@ -16,16 +16,6 @@ Fixes #
|
||||
|
||||
---
|
||||
|
||||
## 🤖 AI Assistance (**X** in brackets)
|
||||
|
||||
> If you used an AI tool (GitHub Copilot, Claude, ChatGPT, etc.) to write or generate any scripts in this PR, you **must** confirm compliance below.
|
||||
> Select exactly one option.
|
||||
|
||||
- [ ] **No AI used** – Scripts were written without AI assistance.
|
||||
- [ ] **AI was used** – I confirm the scripts were built using [`AGENTS.md`](https://github.com/community-scripts/ProxmoxVED/blob/main/AGENTS.md) and [`.github/agents/pve-script-creator.agent.md`](https://github.com/community-scripts/ProxmoxVED/blob/main/.github/agents/pve-script-creator.agent.md) as guidance, and the output has been reviewed and corrected to match those guidelines.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Type of Change (**X** in brackets)
|
||||
|
||||
- [ ] 🐞 **Bug fix** – Resolves an issue without breaking functionality.
|
||||
|
||||
-2
@@ -6,8 +6,6 @@ on:
|
||||
- main
|
||||
paths:
|
||||
- "ct/**.sh"
|
||||
- "tools/**.sh"
|
||||
- "vm/**.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
+1
-3
@@ -24,9 +24,7 @@ generate_headers() {
|
||||
|
||||
app_name=$(grep -oP '^APP="\K[^"]+' "$script" 2>/dev/null)
|
||||
if [[ -n "$app_name" ]]; then
|
||||
# core.func/vm-core.func look the header up as "${APP,,}" without spaces,
|
||||
# so the generated file has to be named after APP - not after the script.
|
||||
output_file="${headers_dir}/$(echo "${app_name,,}" | tr -d ' ')"
|
||||
output_file="${headers_dir}/$(basename "${script%.*}")"
|
||||
figlet_output=$(figlet -w 500 -f slant "$app_name")
|
||||
if [[ -n "$figlet_output" ]]; then
|
||||
echo "$figlet_output" >"$output_file"
|
||||
|
||||
+156
-139
@@ -83,9 +83,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -99,14 +96,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
|
||||
<details>
|
||||
<summary><h4>August (1 entries)</h4></summary>
|
||||
|
||||
[View August 2026 Changelog](.github/changelogs/2026/08.md)
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><h4>July (31 entries)</h4></summary>
|
||||
<summary><h4>July (25 entries)</h4></summary>
|
||||
|
||||
[View July 2026 Changelog](.github/changelogs/2026/07.md)
|
||||
|
||||
@@ -518,142 +508,16 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
</details>
|
||||
|
||||
## 2026-08-04
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Obsidian-LiveSync ([#16233](https://github.com/community-scripts/ProxmoxVE/pull/16233))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- passwordpusher: dynamically read Ruby version from .ruby-version file [@Copilot](https://github.com/Copilot) ([#16242](https://github.com/community-scripts/ProxmoxVE/pull/16242))
|
||||
- fix(salt): write version cache to ~/.salt, not /~.salt [@TowyTowy](https://github.com/TowyTowy) ([#16265](https://github.com/community-scripts/ProxmoxVE/pull/16265))
|
||||
- AFFiNE: fix version and build type reported by the app itself [@MickLesk](https://github.com/MickLesk) ([#16251](https://github.com/community-scripts/ProxmoxVE/pull/16251))
|
||||
- Passbolt: fetch GPG key from Passbolt's own host instead of the flaky keyserver [@MickLesk](https://github.com/MickLesk) ([#16248](https://github.com/community-scripts/ProxmoxVE/pull/16248))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Opencloud: Pin version to 7.4.0 [@vhsdream](https://github.com/vhsdream) ([#16257](https://github.com/community-scripts/ProxmoxVE/pull/16257))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Bump NodeJS Versions of several scripts [@MickLesk](https://github.com/MickLesk) ([#16230](https://github.com/community-scripts/ProxmoxVE/pull/16230))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- tools.func: never delete ubuntu.sources (or other distro base sources) as orphaned [@MickLesk](https://github.com/MickLesk) ([#16250](https://github.com/community-scripts/ProxmoxVE/pull/16250))
|
||||
- tools.func: complete a stale/partial backup manifest instead of trusting it as-is [@MickLesk](https://github.com/MickLesk) ([#16252](https://github.com/community-scripts/ProxmoxVE/pull/16252))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Refactor: harmonize tools/addon and move boilerplate into core.func [@MickLesk](https://github.com/MickLesk) ([#16202](https://github.com/community-scripts/ProxmoxVE/pull/16202))
|
||||
|
||||
## 2026-08-03
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Correction to link in Paperless-NGX update script [@jsspen](https://github.com/jsspen) ([#16241](https://github.com/community-scripts/ProxmoxVE/pull/16241))
|
||||
- fix restore env in split pro [@johanngrobe](https://github.com/johanngrobe) ([#16228](https://github.com/community-scripts/ProxmoxVE/pull/16228))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- core: read all interactive prompts from /dev/tty, drain leftover input on read failure (hotfix) [@MickLesk](https://github.com/MickLesk) ([#16235](https://github.com/community-scripts/ProxmoxVE/pull/16235))
|
||||
|
||||
## 2026-08-02
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Portainer as Addon [@MickLesk](https://github.com/MickLesk) ([#16200](https://github.com/community-scripts/ProxmoxVE/pull/16200))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- LibreNMS: Ensure ipmitool dependency is installed [@tremor021](https://github.com/tremor021) ([#16219](https://github.com/community-scripts/ProxmoxVE/pull/16219))
|
||||
- Bitfocus Companion: add libatomic1 dependency [@tremor021](https://github.com/tremor021) ([#16212](https://github.com/community-scripts/ProxmoxVE/pull/16212))
|
||||
- fix(dispatcharr): add recordings and dvr queues to celery worker [@eXistC](https://github.com/eXistC) ([#16204](https://github.com/community-scripts/ProxmoxVE/pull/16204))
|
||||
- add retry for uv - same as immich [@asylumexp](https://github.com/asylumexp) ([#16203](https://github.com/community-scripts/ProxmoxVE/pull/16203))
|
||||
- Fix for cross-seed node version regression [@TorinFrancis](https://github.com/TorinFrancis) ([#16209](https://github.com/community-scripts/ProxmoxVE/pull/16209))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- chore: remove portainer setup from several scripts (moved to addon) [@MickLesk](https://github.com/MickLesk) ([#16201](https://github.com/community-scripts/ProxmoxVE/pull/16201))
|
||||
|
||||
## 2026-08-01
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Update bazarr-install.sh [@asylumexp](https://github.com/asylumexp) ([#16191](https://github.com/community-scripts/ProxmoxVE/pull/16191))
|
||||
- fix romm missing 7z [@asylumexp](https://github.com/asylumexp) ([#16194](https://github.com/community-scripts/ProxmoxVE/pull/16194))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- add CLEANUPARR_CONFIG_PATH, CLEANUPARR_LOGS_PATH vars [@asylumexp](https://github.com/asylumexp) ([#16193](https://github.com/community-scripts/ProxmoxVE/pull/16193))
|
||||
|
||||
## 2026-07-31
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Docmost: cleanup folder at update [@MickLesk](https://github.com/MickLesk) ([#16177](https://github.com/community-scripts/ProxmoxVE/pull/16177))
|
||||
- Firecrawl: Add dependency [@tremor021](https://github.com/tremor021) ([#16174](https://github.com/community-scripts/ProxmoxVE/pull/16174))
|
||||
|
||||
## 2026-07-30
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Firecrawl ([#16156](https://github.com/community-scripts/ProxmoxVE/pull/16156))
|
||||
- OmniRoute ([#16155](https://github.com/community-scripts/ProxmoxVE/pull/16155))
|
||||
- PegaProx ([#16154](https://github.com/community-scripts/ProxmoxVE/pull/16154))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Immich: Pin version to 3.1.0 [@vhsdream](https://github.com/vhsdream) ([#16170](https://github.com/community-scripts/ProxmoxVE/pull/16170))
|
||||
- romm: remove stale 1.x alembic migrations on update [@Darkatek7](https://github.com/Darkatek7) ([#16101](https://github.com/community-scripts/ProxmoxVE/pull/16101))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Medusa: convert the non-free unrar source to deb822 format [@angusmaul](https://github.com/angusmaul) ([#16093](https://github.com/community-scripts/ProxmoxVE/pull/16093))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools.func: support dynamic gitlab URL | add setup_mysql_db function [@MickLesk](https://github.com/MickLesk) ([#16166](https://github.com/community-scripts/ProxmoxVE/pull/16166))
|
||||
- core: add configurable host CA inheritance during bootstrap [@MickLesk](https://github.com/MickLesk) ([#15889](https://github.com/community-scripts/ProxmoxVE/pull/15889))
|
||||
|
||||
## 2026-07-29
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- backup virtual printer in bambuddy [@asylumexp](https://github.com/asylumexp) ([#16142](https://github.com/community-scripts/ProxmoxVE/pull/16142))
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- backup virtual printer in bambuddy [@asylumexp](https://github.com/asylumexp) ([#16142](https://github.com/community-scripts/ProxmoxVE/pull/16142))
|
||||
- ImmichFrame: check .NET SDK before update deployment [@aidaskni](https://github.com/aidaskni) ([#16104](https://github.com/community-scripts/ProxmoxVE/pull/16104))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Bichon: Migration for V2 Release [@MickLesk](https://github.com/MickLesk) ([#16145](https://github.com/community-scripts/ProxmoxVE/pull/16145))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: Harden remote func bootstrapping with dns issues [@MickLesk](https://github.com/MickLesk) ([#16146](https://github.com/community-scripts/ProxmoxVE/pull/16146))
|
||||
|
||||
## 2026-07-28
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
@@ -1187,3 +1051,156 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Removed deprecated parameter in Filebrowser Quantum configuration [@alpargatagazer](https://github.com/alpargatagazer) ([#15573](https://github.com/community-scripts/ProxmoxVE/pull/15573))
|
||||
|
||||
## 2026-07-02
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Rackula ([#15465](https://github.com/community-scripts/ProxmoxVE/pull/15465))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- typo: fix npm update to npm install for n8n [@MickLesk](https://github.com/MickLesk) ([#15545](https://github.com/community-scripts/ProxmoxVE/pull/15545))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Frigate: bump to v0.17.2 [@MickLesk](https://github.com/MickLesk) ([#15536](https://github.com/community-scripts/ProxmoxVE/pull/15536))
|
||||
|
||||
- #### 💥 Breaking Changes
|
||||
|
||||
- Revert "Immich v3.0.0" [@MickLesk](https://github.com/MickLesk) ([#15558](https://github.com/community-scripts/ProxmoxVE/pull/15558))
|
||||
- Immich v3.0.0 [@vhsdream](https://github.com/vhsdream) ([#15153](https://github.com/community-scripts/ProxmoxVE/pull/15153))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- tools.func: configure pnpm to allow all build scripts for environments [@MickLesk](https://github.com/MickLesk) ([#15532](https://github.com/community-scripts/ProxmoxVE/pull/15532))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- feat(build.func): add var_ignore_disable to bypass disabled-script guard [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#15544](https://github.com/community-scripts/ProxmoxVE/pull/15544))
|
||||
|
||||
## 2026-07-01
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- iVentoy ([#15503](https://github.com/community-scripts/ProxmoxVE/pull/15503))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Stirling-PDF: patch libicudata execstack flag for LXC container compatibility [@MickLesk](https://github.com/MickLesk) ([#15531](https://github.com/community-scripts/ProxmoxVE/pull/15531))
|
||||
- FlowiseAI: align install to use pnpm instead of npm to fix missing dependencies [@MickLesk](https://github.com/MickLesk) ([#15530](https://github.com/community-scripts/ProxmoxVE/pull/15530))
|
||||
- Vaultwarden: handle version detection failure gracefully in update [@MickLesk](https://github.com/MickLesk) ([#15526](https://github.com/community-scripts/ProxmoxVE/pull/15526))
|
||||
- homarr: fix: update-fail [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15512](https://github.com/community-scripts/ProxmoxVE/pull/15512))
|
||||
- n8n: pin version to 2.27.5 [@tremor021](https://github.com/tremor021) ([#15516](https://github.com/community-scripts/ProxmoxVE/pull/15516))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- [arm64] feat: iventory arm64 support [@asylumexp](https://github.com/asylumexp) ([#15521](https://github.com/community-scripts/ProxmoxVE/pull/15521))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- core: fix SDN vnet network parameter to use bridge instead of vnet [@MickLesk](https://github.com/MickLesk) ([#15527](https://github.com/community-scripts/ProxmoxVE/pull/15527))
|
||||
- tools.func: use safe variable expansion in check_for_gh_release RETURN trap [@MickLesk](https://github.com/MickLesk) ([#15529](https://github.com/community-scripts/ProxmoxVE/pull/15529))
|
||||
|
||||
## 2026-06-30
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Refactor: Use heredoc when creating env files and creds/other [@tremor021](https://github.com/tremor021) ([#15469](https://github.com/community-scripts/ProxmoxVE/pull/15469))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- [tools/pve/*.sh] https://download.proxmox.com -> http://download.proxmox.com (PVE8 Only) [@galeksandrp](https://github.com/galeksandrp) ([#15498](https://github.com/community-scripts/ProxmoxVE/pull/15498))
|
||||
|
||||
## 2026-06-29
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Koffan ([#15467](https://github.com/community-scripts/ProxmoxVE/pull/15467))
|
||||
- Etherpad ([#15468](https://github.com/community-scripts/ProxmoxVE/pull/15468))
|
||||
- Flame ([#15464](https://github.com/community-scripts/ProxmoxVE/pull/15464))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- chore(ct): sync snapotter defaults with PocketBase [@github-actions[bot]](https://github.com/github-actions[bot]) ([#15472](https://github.com/community-scripts/ProxmoxVE/pull/15472))
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- feat: update nginx proxy manager to trixie [@asylumexp](https://github.com/asylumexp) ([#15457](https://github.com/community-scripts/ProxmoxVE/pull/15457))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- [tools.func]: add edit_yaml_config function [@tremor021](https://github.com/tremor021) ([#15484](https://github.com/community-scripts/ProxmoxVE/pull/15484))
|
||||
|
||||
## 2026-06-28
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 💥 Breaking Changes
|
||||
|
||||
- remove: promtail as EOL and other fixes [@asylumexp](https://github.com/asylumexp) ([#15455](https://github.com/community-scripts/ProxmoxVE/pull/15455))
|
||||
|
||||
## 2026-06-27
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- tool: add disk-health tool (SMART + NVMe) [@MickLesk](https://github.com/MickLesk) ([#15417](https://github.com/community-scripts/ProxmoxVE/pull/15417))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Deluge openssl fix [@asylumexp](https://github.com/asylumexp) ([#15435](https://github.com/community-scripts/ProxmoxVE/pull/15435))
|
||||
- fix command syntax in tunarr.sh [@asylumexp](https://github.com/asylumexp) ([#15434](https://github.com/community-scripts/ProxmoxVE/pull/15434))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Storyteller: bump Node.js version to Node 24 [@thinusn](https://github.com/thinusn) ([#15439](https://github.com/community-scripts/ProxmoxVE/pull/15439))
|
||||
|
||||
### ❔ Uncategorized
|
||||
|
||||
- fix(endurain): replace Poetry/uv-pip backend setup with uv sync --frozen --no-dev [@Copilot](https://github.com/Copilot) ([#15429](https://github.com/community-scripts/ProxmoxVE/pull/15429))
|
||||
|
||||
## 2026-06-26
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- Termix: Update Nginx configuration file paths [@xyzulu](https://github.com/xyzulu) ([#15397](https://github.com/community-scripts/ProxmoxVE/pull/15397))
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- Docuseal: use real SECRET_KEY_BASE for db:migrate on update [@MickLesk](https://github.com/MickLesk) ([#15411](https://github.com/community-scripts/ProxmoxVE/pull/15411))
|
||||
- bun: correct install for degoog [@MickLesk](https://github.com/MickLesk) ([#15412](https://github.com/community-scripts/ProxmoxVE/pull/15412))
|
||||
- fix databasus update/install errors [@asylumexp](https://github.com/asylumexp) ([#15403](https://github.com/community-scripts/ProxmoxVE/pull/15403))
|
||||
|
||||
### 💾 Core
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- tools.func: fix setup_docker - don't abort update on docker pull failure [@MickLesk](https://github.com/MickLesk) ([#15410](https://github.com/community-scripts/ProxmoxVE/pull/15410))
|
||||
- fix(build.func): set /dev/kfd GID in fix_gpu_gids for AMD ROCm [@jamiej](https://github.com/jamiej) ([#15401](https://github.com/community-scripts/ProxmoxVE/pull/15401))
|
||||
- fix alpine mktmp error [@asylumexp](https://github.com/asylumexp) ([#15398](https://github.com/community-scripts/ProxmoxVE/pull/15398))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Refactor: reduce IP-Tag resource usage and clean up ShellCheck findings [@MickLesk](https://github.com/MickLesk) ([#15418](https://github.com/community-scripts/ProxmoxVE/pull/15418))
|
||||
- QoL: kernel-clean: Validate kernel selection input [@MickLesk](https://github.com/MickLesk) ([#15414](https://github.com/community-scripts/ProxmoxVE/pull/15414))
|
||||
- QoL: clean-lxcs exclude matching and set -e cancel handling [@MickLesk](https://github.com/MickLesk) ([#15413](https://github.com/community-scripts/ProxmoxVE/pull/15413))
|
||||
- QoL: Harden microcode download/install in microcode and pbs-microcode [@MickLesk](https://github.com/MickLesk) ([#15415](https://github.com/community-scripts/ProxmoxVE/pull/15415))
|
||||
- QoL: scaling-governor extend selection and guard missing cpufreq [@MickLesk](https://github.com/MickLesk) ([#15416](https://github.com/community-scripts/ProxmoxVE/pull/15416))
|
||||
+1
-1
@@ -30,7 +30,7 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
RELEASE=$(get_latest_github_release "actualbudget/actual")
|
||||
if [[ -f /opt/actualbudget-data/config.json ]]; then
|
||||
if check_for_gh_release "actualbudget" "actualbudget/actual"; then
|
||||
|
||||
@@ -81,8 +81,6 @@ TURBO
|
||||
|
||||
export NODE_OPTIONS="--max-old-space-size=2048"
|
||||
$STD yarn install
|
||||
$STD bash ./scripts/set-version.sh "$(cat ~/.affine_app)"
|
||||
export BUILD_TYPE=stable
|
||||
$STD npm install -g typescript
|
||||
|
||||
$STD yarn affine @affine/native build
|
||||
|
||||
@@ -118,19 +118,10 @@ function update_script() {
|
||||
export UV_COMPILE_BYTECODE="1"
|
||||
export UV_LINK_MODE="copy"
|
||||
export UV_NATIVE_TLS="1"
|
||||
export UV_HTTP_TIMEOUT="300"
|
||||
export RUSTUP_PERMIT_COPY_RENAME="true"
|
||||
export UV_PYTHON_INSTALL_DIR="/usr/local/bin"
|
||||
cd /opt/authentik
|
||||
for attempt in 1 2 3; do
|
||||
if [[ $attempt -eq 3 ]]; then
|
||||
$STD uv sync --frozen --no-install-project --no-dev
|
||||
break
|
||||
fi
|
||||
$STD uv sync --frozen --no-install-project --no-dev && break
|
||||
msg_warn "uv sync attempt $attempt failed, retrying..."
|
||||
sleep $((attempt * 15))
|
||||
done
|
||||
chown -R authentik:authentik /opt/authentik
|
||||
msg_ok "Updated python server"
|
||||
|
||||
|
||||
+47
-33
@@ -34,27 +34,30 @@ function update_script() {
|
||||
CURRENT_VERSION=$(cat /root/.bichon)
|
||||
fi
|
||||
|
||||
if [[ $CURRENT_VERSION != 1.* && $CURRENT_VERSION != 2.* ]]; then
|
||||
msg_error "Installed ${APP} version (${CURRENT_VERSION}) is too old for an automatic update to v2.x."
|
||||
msg_error "Please create a new ${APP} container and migrate your data manually."
|
||||
msg_error "Guide: https://github.com/rustmailer/bichon/wiki/Bichon-v2.x-Migration-Guide"
|
||||
exit
|
||||
fi
|
||||
|
||||
MIGRATE_V2=0
|
||||
if [[ $CURRENT_VERSION == 1.* ]]; then
|
||||
MIGRATE_V2=1
|
||||
STORAGE_KB=$(du -sk /opt/bichon-data/bichon-storage 2>/dev/null | awk '{print $1}')
|
||||
FREE_KB=$(df -Pk /opt/bichon-data | awk 'NR==2 {print $4}')
|
||||
if [[ -n "$STORAGE_KB" && -n "$FREE_KB" && "$FREE_KB" -lt "$STORAGE_KB" ]]; then
|
||||
echo -e "\n${RD}Warning: migration needs about $((STORAGE_KB / 1024))MB, only $((FREE_KB / 1024))MB free.${CL}"
|
||||
echo -e "${RD}The new bichon-blob store is written alongside the existing fjall data.${CL}"
|
||||
MIGRATE_V1=0
|
||||
if [[ $CURRENT_VERSION == 0.* ]]; then
|
||||
MIGRATE_V1=1
|
||||
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
if [ "$DISK_USAGE" -gt 50 ]; then
|
||||
echo -e "\n${RD}Warning: Less than 50% free storage remaining on the root disk.${CL}"
|
||||
echo -e "${RD}Bichon v1 data migration temporarily duplicates data and requires free space for it.${CL}"
|
||||
read -r -p "Are you sure you want to proceed with the update? (y/N): " proceed
|
||||
if [[ ! $proceed =~ ^[Yy]$ ]]; then
|
||||
msg_error "Update cancelled by user."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
RAM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
|
||||
if [ "$RAM_TOTAL" -lt 2000 ]; then
|
||||
echo -e "\n${RD}Warning: LXC has less than 2GB of RAM allocated (${RAM_TOTAL}MB).${CL}"
|
||||
echo -e "${RD}Bichon v1 data migration consumes significant memory and may crash if insufficient.${CL}"
|
||||
read -r -p "Are you sure you want to proceed with the update? (y/N): " proceed_ram
|
||||
if [[ ! $proceed_ram =~ ^[Yy]$ ]]; then
|
||||
msg_error "Update cancelled by user."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if check_for_gh_release "bichon" "rustmailer/bichon"; then
|
||||
@@ -64,44 +67,55 @@ function update_script() {
|
||||
|
||||
create_backup /opt/bichon/bichon.env
|
||||
|
||||
if [ "$MIGRATE_V1" -eq 1 ] && [ "$CURRENT_VERSION" != "0.3.7" ]; then
|
||||
msg_info "Updating to intermediate version v0.3.7"
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "bichon" "rustmailer/bichon" "prebuild" "v0.3.7" "/opt/bichon" "bichon-*-$(arch_resolve "x86_64" "aarch64")-unknown-linux-gnu.tar.gz"
|
||||
restore_backup
|
||||
systemctl start bichon
|
||||
sleep 30
|
||||
systemctl stop bichon
|
||||
msg_ok "Intermediate update completed"
|
||||
fi
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "bichon" "rustmailer/bichon" "prebuild" "latest" "/opt/bichon" "bichon-*-$(arch_resolve "x86_64" "aarch64")-unknown-linux-gnu.tar.gz"
|
||||
restore_backup
|
||||
|
||||
if [ "$MIGRATE_V2" -eq 1 ]; then
|
||||
msg_info "Migrating storage from fjall to bichon-blob (patience)"
|
||||
if [ "$MIGRATE_V1" -eq 1 ]; then
|
||||
msg_info "Running Bichon v1 Data Migration (patience)"
|
||||
$STD apt install -y expect
|
||||
# Menu: 0 Reset Password, 1 Migrate v0.3.7, 2 Migrate v1.x, 3 Exit
|
||||
$STD expect <<'EOF'
|
||||
set timeout -1
|
||||
spawn /opt/bichon/bichon-admin
|
||||
expect "*Select an operation*"
|
||||
send "\033\[B\033\[B\r"
|
||||
send "\033\[B\r"
|
||||
expect "*--bichon-root-dir*"
|
||||
send "/opt/bichon-data\r"
|
||||
expect "*--bichon-index-dir*"
|
||||
send "\r"
|
||||
expect "*--bichon-data-dir*"
|
||||
send "\r"
|
||||
expect "*batch size*"
|
||||
expect "*Ready to migrate?*"
|
||||
send "y"
|
||||
expect "*Enter batch size*"
|
||||
send "1000\r"
|
||||
expect eof
|
||||
catch wait
|
||||
EOF
|
||||
$STD apt remove --purge expect -y
|
||||
$STD apt autoremove -y
|
||||
msg_ok "Migration completed"
|
||||
|
||||
if [[ ! -d /opt/bichon-data/bichon-storage/blobs ]] ||
|
||||
[[ "$(cat /opt/bichon-data/STORAGE_VERSION 2>/dev/null)" != "2" ]]; then
|
||||
msg_error "Storage migration did not complete - service left stopped, legacy data untouched."
|
||||
msg_error "Run /opt/bichon/bichon-admin manually and select 'Migrate v1.x Storage to v2.x'."
|
||||
exit
|
||||
fi
|
||||
msg_ok "Migrated storage to bichon-blob"
|
||||
msg_info "Cleaning up legacy Bichon v0.x storage files"
|
||||
rm -rf /opt/bichon-data/envelope
|
||||
rm -rf /opt/bichon-data/eml
|
||||
rm -f /opt/bichon-data/mailbox.db
|
||||
rm -f /opt/bichon-data/meta.db
|
||||
msg_ok "Cleanup completed"
|
||||
|
||||
msg_info "Removing legacy fjall files"
|
||||
rm -rf /opt/bichon-data/bichon-storage/keyspaces
|
||||
rm -f /opt/bichon-data/bichon-storage/0.jnl
|
||||
rm -f /opt/bichon-data/bichon-storage/lock
|
||||
rm -f /opt/bichon-data/bichon-storage/version
|
||||
msg_ok "Removed legacy fjall files"
|
||||
msg_info "Updating Bichon service for v1"
|
||||
sed -i 's|ExecStart=/opt/bichon/bichon|ExecStart=/opt/bichon/bichon-server|g; s|RestartSec=5|RestartSec=5\n\nLimitNOFILE=65536|g' /etc/systemd/system/bichon.service
|
||||
systemctl daemon-reload
|
||||
msg_ok "Service updated"
|
||||
fi
|
||||
|
||||
msg_info "Starting service"
|
||||
|
||||
@@ -30,8 +30,6 @@ function update_script() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ensure_dependencies libatomic1
|
||||
|
||||
RELEASE_JSON=$(curl -fsSL "https://api.bitfocus.io/v1/product/companion/packages?limit=20")
|
||||
PACKAGE_JSON=$(echo "$RELEASE_JSON" | jq -c \
|
||||
--arg target "linux-$(arch_resolve "tgz" "arm64-tgz")" \
|
||||
|
||||
+1
-13
@@ -33,19 +33,7 @@ function update_script() {
|
||||
systemctl stop cleanuparr
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
if [[ ! -d /etc/cleanuparr ]]; then
|
||||
msg_info "Migrating Configuration to /etc/cleanuparr"
|
||||
mv /opt/cleanuparr/config /etc/cleanuparr
|
||||
mkdir -p /etc/cleanuparr /var/log/cleanuparr
|
||||
rm -rf /etc/cleanuparr/logs
|
||||
sed -i -e 's|^Environment="CONFIG_DIR=.*|Environment="CLEANUPARR_CONFIG_PATH=/etc/cleanuparr"|' \
|
||||
-e '/^Environment="CLEANUPARR_CONFIG_PATH=/a Environment="CLEANUPARR_LOGS_PATH=/var/log/cleanuparr"' \
|
||||
/etc/systemd/system/cleanuparr.service
|
||||
systemctl daemon-reload
|
||||
msg_ok "Migrated Configuration to /etc/cleanuparr"
|
||||
fi
|
||||
|
||||
create_backup /etc/cleanuparr
|
||||
create_backup /opt/cleanuparr/config
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip"
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ function update_script() {
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
ensure_dependencies build-essential
|
||||
|
||||
if command -v cross-seed &>/dev/null; then
|
||||
|
||||
+16
-5
@@ -37,9 +37,20 @@ function update_script() {
|
||||
fi
|
||||
|
||||
if docker ps -a --format '{{.Image}}' | grep -q '^portainer/portainer-ce:latest$'; then
|
||||
msg_warn "Portainer is now managed by a dedicated addon script and is no longer updated here."
|
||||
echo -e "${TAB}Update/migrate it with:"
|
||||
echo -e "${TAB}${TAB}${GN}bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)\"${CL}"
|
||||
msg_info "Updating Portainer"
|
||||
$STD docker pull portainer/portainer-ce:latest
|
||||
$STD docker stop portainer
|
||||
$STD docker rm portainer
|
||||
$STD docker volume create portainer_data >/dev/null 2>&1
|
||||
$STD docker run -d \
|
||||
-p 8000:8000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
msg_ok "Updated Portainer"
|
||||
fi
|
||||
|
||||
if docker ps -a --format '{{.Names}}' | grep -q '^portainer_agent$'; then
|
||||
@@ -66,5 +77,5 @@ description
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Portainer is available as a separate addon. Install it with:${CL}"
|
||||
echo -e "${GATEWAY}${BGN}bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)\"${CL}"
|
||||
echo -e "${INFO}${YW} If you installed Portainer, access it at the following URL:${CL}"
|
||||
echo -e "${GATEWAY}${BGN}https://${IP}:9443${CL}"
|
||||
|
||||
+3
-3
@@ -37,9 +37,9 @@ function update_script() {
|
||||
systemctl stop docmost
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
create_backup /opt/docmost/.env /opt/docmost/data
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball"
|
||||
create_backup /opt/docmost/.env \
|
||||
/opt/docmost/data
|
||||
fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball"
|
||||
|
||||
restore_backup
|
||||
|
||||
|
||||
@@ -1,93 +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: esatbayhan
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.firecrawl.dev/
|
||||
|
||||
APP="Firecrawl"
|
||||
var_tags="${var_tags:-scraping;ai;crawler}"
|
||||
var_cpu="${var_cpu:-4}"
|
||||
var_ram="${var_ram:-4096}"
|
||||
var_disk="${var_disk:-30}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-no}"
|
||||
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/firecrawl/apps/api ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
ensure_dependencies build-essential
|
||||
|
||||
if check_for_gh_release "firecrawl" "firecrawl/firecrawl"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop firecrawl firecrawl-playwright
|
||||
msg_ok "Stopped Services"
|
||||
|
||||
create_backup /opt/firecrawl/.env
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "firecrawl" "firecrawl/firecrawl" "tarball" "latest" "/opt/firecrawl"
|
||||
|
||||
restore_backup
|
||||
|
||||
FDB_VERSION="$(awk -F= '/^ARG FDB_VERSION=/{print $2; exit}' /opt/firecrawl/apps/api/Dockerfile)"
|
||||
if [[ -z "$FDB_VERSION" ]]; then
|
||||
msg_error "FDB_VERSION pin not found in upstream Dockerfile"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$(dpkg-query -W -f='${Version}' foundationdb-clients 2>/dev/null)" != "${FDB_VERSION}-"* ]]; then
|
||||
FDB_ARCH="$(get_system_arch)"
|
||||
[[ "$FDB_ARCH" == "arm64" ]] && FDB_ARCH="aarch64"
|
||||
fetch_and_deploy_gh_release "foundationdb-clients" "apple/foundationdb" "binary" "$FDB_VERSION" "/opt/foundationdb-clients" "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb"
|
||||
fi
|
||||
|
||||
msg_info "Building Go Library"
|
||||
cd /opt/firecrawl/apps/api/sharedLibs/go-html-to-md
|
||||
$STD go build -o libhtml-to-markdown.so -buildmode=c-shared html-to-markdown.go
|
||||
msg_ok "Built Go Library"
|
||||
|
||||
msg_info "Building Firecrawl API"
|
||||
source "$HOME/.cargo/env"
|
||||
cd /opt/firecrawl/apps/api
|
||||
$STD pnpm install --frozen-lockfile
|
||||
$STD pnpm build
|
||||
CI=true $STD pnpm prune --prod --ignore-scripts
|
||||
msg_ok "Built Firecrawl API"
|
||||
|
||||
msg_info "Building Playwright Service"
|
||||
cd /opt/firecrawl/apps/playwright-service-ts
|
||||
$STD npm install
|
||||
$STD npx playwright install chromium --with-deps
|
||||
$STD npm run build
|
||||
$STD npm prune --omit=dev
|
||||
msg_ok "Built Playwright Service"
|
||||
|
||||
msg_info "Starting Services"
|
||||
systemctl start firecrawl-playwright firecrawl
|
||||
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 "${GATEWAY}${BGN}http://${IP}:3002${CL}"
|
||||
@@ -1,6 +0,0 @@
|
||||
_______ __
|
||||
/ ____(_)_______ ______________ __ __/ /
|
||||
/ /_ / / ___/ _ \/ ___/ ___/ __ `/ | /| / / /
|
||||
/ __/ / / / / __/ /__/ / / /_/ /| |/ |/ / /
|
||||
/_/ /_/_/ \___/\___/_/ \__,_/ |__/|__/_/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
_____
|
||||
/ ___/_________ _____ ____ ____ __ __
|
||||
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / /
|
||||
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ /
|
||||
/____/\___/\__,_/_/ /_/\____/ .___/\__, /
|
||||
/_/ /____/
|
||||
@@ -1,6 +0,0 @@
|
||||
____ __ _ ___ __ _ _____
|
||||
/ __ \/ /_ _____(_)___/ (_)___ _____ / / (_) _____ / ___/__ ______ _____
|
||||
/ / / / __ \/ ___/ / __ / / __ `/ __ \______/ / / / | / / _ \\__ \/ / / / __ \/ ___/
|
||||
/ /_/ / /_/ (__ ) / /_/ / / /_/ / / / /_____/ /___/ /| |/ / __/__/ / /_/ / / / / /__
|
||||
\____/_.___/____/_/\__,_/_/\__,_/_/ /_/ /_____/_/ |___/\___/____/\__, /_/ /_/\___/
|
||||
/____/
|
||||
@@ -1,6 +0,0 @@
|
||||
____ _ ____ __
|
||||
/ __ \____ ___ ____ (_) __ \____ __ __/ /____
|
||||
/ / / / __ `__ \/ __ \/ / /_/ / __ \/ / / / __/ _ \
|
||||
/ /_/ / / / / / / / / / / _, _/ /_/ / /_/ / /_/ __/
|
||||
\____/_/ /_/ /_/_/ /_/_/_/ |_|\____/\__,_/\__/\___/
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
____ ____
|
||||
/ __ \___ ____ _____ _/ __ \_________ _ __
|
||||
/ /_/ / _ \/ __ `/ __ `/ /_/ / ___/ __ \| |/_/
|
||||
/ ____/ __/ /_/ / /_/ / ____/ / / /_/ /> <
|
||||
/_/ \___/\__, /\__,_/_/ /_/ \____/_/|_|
|
||||
/____/
|
||||
+1
-2
@@ -110,7 +110,7 @@ EOF
|
||||
msg_ok "Image-processing libraries up to date"
|
||||
fi
|
||||
|
||||
RELEASE="v3.1.0"
|
||||
RELEASE="v3.0.3"
|
||||
if check_for_gh_release "Immich" "immich-app/immich" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
|
||||
if [[ $(cat ~/.immich) > "2.5.1" ]]; then
|
||||
msg_info "Enabling Maintenance Mode"
|
||||
@@ -310,7 +310,6 @@ EOF
|
||||
grep -rl /usr/src | xargs -n1 sed -i "s|\/usr/src|$INSTALL_DIR|g"
|
||||
grep -rlE "'/build'" | xargs -n1 sed -i "s|'/build'|'$APP_DIR'|g"
|
||||
sed -i "s@\"/cache\"@\"$INSTALL_DIR/cache\"@g" "$ML_DIR"/immich_ml/config.py
|
||||
[[ ! -f "$GEO_DIR/countryInfo.txt" ]] && curl_with_retry "https://download.geonames.org/export/dump/countryInfo.txt" "countryInfo.txt"
|
||||
ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$APP_DIR"/upload
|
||||
ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$ML_DIR"/upload
|
||||
ln -s "$GEO_DIR" "$APP_DIR"
|
||||
|
||||
@@ -28,9 +28,6 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
ensure_dependencies ipmitool
|
||||
|
||||
if check_for_gh_release "librenms" "librenms/librenms"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop php8.4-fpm librenms-scheduler.timer
|
||||
|
||||
@@ -1,61 +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 (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/vrtmrz/obsidian-livesync | https://couchdb.apache.org/
|
||||
|
||||
APP="Obsidian-LiveSync"
|
||||
var_tags="${var_tags:-documents;notes}"
|
||||
var_cpu="${var_cpu:-1}"
|
||||
var_ram="${var_ram:-1024}"
|
||||
var_disk="${var_disk:-8}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-yes}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -f /opt/couchdb/etc/local.d/obsidian-livesync.ini ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
msg_info "Stopping CouchDB"
|
||||
systemctl stop couchdb
|
||||
msg_ok "Stopped CouchDB"
|
||||
|
||||
create_backup /var/lib/couchdb /opt/couchdb/etc/local.d/obsidian-livesync.ini /opt/obsidian-livesync/.env
|
||||
|
||||
msg_info "Updating Container OS"
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
msg_ok "Updated Container OS"
|
||||
|
||||
systemctl stop couchdb
|
||||
restore_backup
|
||||
|
||||
msg_info "Starting CouchDB"
|
||||
systemctl start couchdb
|
||||
msg_ok "Started CouchDB"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW}Configure the Self-hosted LiveSync plugin with the credentials in /opt/obsidian-livesync/.env${CL}"
|
||||
echo -e "${GATEWAY}${BGN}http://${IP}:5984/_utils/${CL}"
|
||||
@@ -1,71 +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 (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/diegosouzapw/OmniRoute
|
||||
|
||||
APP="OmniRoute"
|
||||
var_tags="${var_tags:-ai;gateway;llm}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_disk="${var_disk:-10}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-no}"
|
||||
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/omniroute ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
msg_info "Checking for Updates"
|
||||
local LATEST
|
||||
LATEST=$(npm view omniroute version 2>/dev/null)
|
||||
if [[ -z "$LATEST" ]]; then
|
||||
msg_error "Could not determine latest OmniRoute version"
|
||||
exit
|
||||
fi
|
||||
if [[ "$LATEST" == "$(omniroute --version 2>/dev/null)" ]]; then
|
||||
msg_ok "Already up to date (${LATEST})"
|
||||
exit
|
||||
fi
|
||||
msg_ok "New version available: ${LATEST}"
|
||||
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop omniroute
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Updating OmniRoute to ${LATEST}"
|
||||
$STD npm install -g omniroute@latest
|
||||
msg_ok "Updated OmniRoute to ${LATEST}"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start omniroute
|
||||
msg_ok "Started Service"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:20128${CL}"
|
||||
echo -e "${INFO}${YW} The admin password is stored in /opt/omniroute/.env (INITIAL_PASSWORD)${CL}"
|
||||
+1
-1
@@ -30,7 +30,7 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
RELEASE="v7.4.0"
|
||||
RELEASE="v7.3.0"
|
||||
if check_for_gh_release "OpenCloud" "opencloud-eu/opencloud" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
|
||||
msg_info "Stopping services"
|
||||
systemctl stop opencloud opencloud-wopi
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ function update_script() {
|
||||
echo -e ""
|
||||
msg_custom "🔄" "Migration required to new data structure (/opt/paperless_data/)"
|
||||
msg_custom "📖" "Please follow the migration guide:"
|
||||
echo -e "${GATEWAY}${BGN}https://github.com/community-scripts/ProxmoxVE/pull/9223${CL}"
|
||||
echo -e "${GATEWAY}${BGN}https://github.com/community-scripts/ProxmoxVE/discussions/9223${CL}"
|
||||
echo -e ""
|
||||
msg_custom "⚠️" "Update aborted. Please migrate your data first."
|
||||
exit 253
|
||||
|
||||
@@ -38,7 +38,6 @@ function update_script() {
|
||||
create_backup /opt/passwordpusher/storage /opt/passwordpusher/.env.production
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball"
|
||||
RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
|
||||
msg_info "Installing Gem Dependencies"
|
||||
cd /opt/passwordpusher
|
||||
|
||||
@@ -1,64 +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 (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/PegaProx/project-pegaprox
|
||||
|
||||
APP="PegaProx"
|
||||
var_tags="${var_tags:-proxmox;management}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_disk="${var_disk:-8}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-no}"
|
||||
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/pegaprox ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_release "pegaprox" "PegaProx/project-pegaprox"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop pegaprox
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
create_backup /opt/pegaprox/config /etc/pegaprox/secret.key
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "pegaprox" "PegaProx/project-pegaprox" "tarball"
|
||||
|
||||
msg_info "Updating Python Environment"
|
||||
$STD uv venv --python 3.12 /opt/pegaprox/venv
|
||||
$STD uv pip install --python /opt/pegaprox/venv/bin/python -r /opt/pegaprox/requirements.txt
|
||||
msg_ok "Updated Python Environment"
|
||||
|
||||
restore_backup
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start pegaprox
|
||||
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}https://${IP}:5000${CL}"
|
||||
-10
@@ -30,12 +30,6 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ ! -x /usr/bin/7zz || ! -x /usr/bin/bsdtar ]]; then
|
||||
msg_info "Installing Archive Tools"
|
||||
$STD apt install -y 7zip-standalone libarchive-tools
|
||||
msg_ok "Installed Archive Tools"
|
||||
fi
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
if check_for_gh_release "romm" "rommapp/romm"; then
|
||||
@@ -50,10 +44,6 @@ function update_script() {
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm"
|
||||
|
||||
find /opt/romm/backend/alembic/versions -maxdepth 1 -type f -name '1.*.py' -delete 2>/dev/null || true
|
||||
find /opt/romm/backend/alembic/versions -maxdepth 1 -type f -name '2.0.0_.py' -delete 2>/dev/null || true
|
||||
find /opt/romm/backend -name '__pycache__' -type d -prune -exec rm -rf {} + 2>/dev/null || true
|
||||
|
||||
restore_backup
|
||||
|
||||
msg_info "Updating ROMM"
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ function update_script() {
|
||||
sed -i "s/^\(Pin: version \).*/\1${RELEASE}/" /etc/apt/preferences.d/salt-pin-1001
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
echo "${RELEASE}" >~/.salt
|
||||
echo "${RELEASE}" >/~.salt
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
exit
|
||||
|
||||
+5
-3
@@ -35,16 +35,18 @@ function update_script() {
|
||||
systemctl stop split-pro
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
create_backup /opt/split-pro/.env
|
||||
msg_info "Backing up Data"
|
||||
cp /opt/split-pro/.env /opt/split-pro.env
|
||||
msg_ok "Backed up Data"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "split-pro" "oss-apps/split-pro" "tarball"
|
||||
|
||||
restore_backup
|
||||
|
||||
msg_info "Building Application"
|
||||
cd /opt/split-pro
|
||||
$STD pnpm install --frozen-lockfile
|
||||
$STD pnpm build
|
||||
cp /opt/split-pro.env /opt/split-pro/.env
|
||||
rm -f /opt/split-pro.env
|
||||
ln -sf /opt/split-pro_data/uploads /opt/split-pro/uploads
|
||||
$STD pnpm exec prisma migrate deploy
|
||||
msg_ok "Built Application"
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ EOF
|
||||
fi
|
||||
msg_ok "Migrated Configuration"
|
||||
|
||||
create_backup /opt/termix/data /opt/termix/uploads /opt/termix/.env
|
||||
create_backup /opt/termix/data /opt/termix/uploads
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix" "tarball"
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ function update_script() {
|
||||
systemctl stop watcharr
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
create_backup /opt/watcharr/server/data
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "watcharr" "sbondCo/Watcharr" "tarball"
|
||||
restore_backup
|
||||
|
||||
@@ -19,7 +19,7 @@ $STD apt install -y \
|
||||
g++
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
create_self_signed_cert
|
||||
|
||||
msg_info "Installing Actual Budget"
|
||||
|
||||
@@ -78,8 +78,6 @@ $STD yarn config set enableTelemetry 0
|
||||
export NODE_OPTIONS="--max-old-space-size=4096"
|
||||
export TSC_COMPILE_ON_ERROR=true
|
||||
$STD yarn install
|
||||
$STD bash ./scripts/set-version.sh "$(cat ~/.affine_app)"
|
||||
export BUILD_TYPE=stable
|
||||
$STD npm install -g typescript
|
||||
$STD yarn affine @affine/native build
|
||||
$STD yarn affine @affine/server-native build
|
||||
|
||||
@@ -26,21 +26,23 @@ msg_ok "Installed Docker"
|
||||
get_latest_release() {
|
||||
curl -fsSL https://api.github.com/repos/"$1"/releases/latest | grep '"tag_name":' | cut -d'"' -f4
|
||||
}
|
||||
PORTAINER_LATEST_VERSION=$(get_latest_release "portainer/portainer")
|
||||
DOCKER_COMPOSE_LATEST_VERSION=$(get_latest_release "docker/compose")
|
||||
PORTAINER_AGENT_LATEST_VERSION=$(get_latest_release "portainer/agent")
|
||||
|
||||
read -r -p "${TAB3}Would you like to add Docker Compose? <y/N> " prompt
|
||||
read -r -p "${TAB3}Would you like to add Portainer? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
|
||||
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
|
||||
mkdir -p "$DOCKER_CONFIG"/cli-plugins
|
||||
curl -fsSL https://github.com/docker/compose/releases/download/"$DOCKER_COMPOSE_LATEST_VERSION"/docker-compose-linux-$(arch_resolve "x86_64" "aarch64") -o ~/.docker/cli-plugins/docker-compose
|
||||
chmod +x "$DOCKER_CONFIG"/cli-plugins/docker-compose
|
||||
msg_ok "Installed Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
|
||||
fi
|
||||
|
||||
if prompt_confirm "${TAB3}Would you like to install Portainer (UI) via the community-scripts addon?" "n" 60; then
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)" <<<"y"
|
||||
msg_info "Installing Portainer $PORTAINER_LATEST_VERSION"
|
||||
docker volume create portainer_data >/dev/null
|
||||
$STD docker run -d \
|
||||
-p 8000:8000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
msg_ok "Installed Portainer $PORTAINER_LATEST_VERSION"
|
||||
else
|
||||
read -r -p "${TAB3}Would you like to add the Portainer Agent? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
@@ -55,6 +57,15 @@ else
|
||||
msg_ok "Installed Portainer Agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
fi
|
||||
fi
|
||||
read -r -p "${TAB3}Would you like to add Docker Compose? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
|
||||
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
|
||||
mkdir -p "$DOCKER_CONFIG"/cli-plugins
|
||||
curl -fsSL https://github.com/docker/compose/releases/download/"$DOCKER_COMPOSE_LATEST_VERSION"/docker-compose-linux-$(arch_resolve "x86_64" "aarch64") -o ~/.docker/cli-plugins/docker-compose
|
||||
chmod +x "$DOCKER_CONFIG"/cli-plugins/docker-compose
|
||||
msg_ok "Installed Docker Compose $DOCKER_COMPOSE_LATEST_VERSION"
|
||||
fi
|
||||
|
||||
read -r -p "${TAB3}Would you like to expose the Docker TCP socket? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
|
||||
@@ -122,18 +122,9 @@ export UV_NO_BINARY_PACKAGE="cryptography lxml python-kadmin-rs xmlsec"
|
||||
export UV_COMPILE_BYTECODE="1"
|
||||
export UV_LINK_MODE="copy"
|
||||
export UV_NATIVE_TLS="1"
|
||||
export UV_HTTP_TIMEOUT="300"
|
||||
export UV_PYTHON_INSTALL_DIR="/usr/local/bin"
|
||||
cd /opt/authentik
|
||||
for attempt in 1 2 3; do
|
||||
if [[ $attempt -eq 3 ]]; then
|
||||
$STD uv sync --frozen --no-install-project --no-dev
|
||||
break
|
||||
fi
|
||||
$STD uv sync --frozen --no-install-project --no-dev && break
|
||||
msg_warn "uv sync attempt $attempt failed, retrying..."
|
||||
sleep $((attempt * 15))
|
||||
done
|
||||
cp /opt/authentik/authentik/sources/kerberos/krb5.conf /etc/krb5.conf
|
||||
msg_ok "Setup python server"
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ chmod 775 /opt/bazarr /var/lib/bazarr/
|
||||
sed -i.bak 's/--only-binary=Pillow//g' /opt/bazarr/requirements.txt
|
||||
$STD uv venv --clear /opt/bazarr/venv --python 3.12
|
||||
$STD uv pip install -r /opt/bazarr/requirements.txt --python /opt/bazarr/venv/bin/python3
|
||||
$STD uv pip install psycopg2-binary --python /opt/bazarr/venv/bin/python3
|
||||
msg_ok "Installed Bazarr"
|
||||
|
||||
msg_info "Creating Service"
|
||||
|
||||
@@ -60,7 +60,7 @@ LimitNOFILE=65536
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now bichon
|
||||
msg_ok "Created Service"
|
||||
msg_info "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
|
||||
@@ -14,9 +14,7 @@ network_check
|
||||
update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y \
|
||||
libusb-1.0-0 \
|
||||
libatomic1
|
||||
$STD apt install -y libusb-1.0-0
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Fetching Latest Bitfocus Companion Release"
|
||||
|
||||
@@ -16,7 +16,6 @@ update_os
|
||||
fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip"
|
||||
|
||||
msg_info "Creating Service"
|
||||
mkdir -p /etc/cleanuparr /var/log/cleanuparr
|
||||
cat <<EOF >/etc/systemd/system/cleanuparr.service
|
||||
[Unit]
|
||||
Description=Cleanuparr Daemon
|
||||
@@ -30,8 +29,7 @@ ExecStart=/opt/cleanuparr/Cleanuparr
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment="PORT=11011"
|
||||
Environment="CLEANUPARR_CONFIG_PATH=/etc/cleanuparr"
|
||||
Environment="CLEANUPARR_LOGS_PATH=/var/log/cleanuparr"
|
||||
Environment="CONFIG_DIR=/opt/cleanuparr/config"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -17,7 +17,7 @@ msg_info "Installing Dependencies"
|
||||
$STD apt install -y build-essential
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
|
||||
msg_info "Setup Cross-Seed"
|
||||
$STD npm install cross-seed@latest -g
|
||||
|
||||
@@ -174,7 +174,7 @@ cd /opt/dispatcharr
|
||||
set -a
|
||||
source .env
|
||||
set +a
|
||||
exec uv run celery -A dispatcharr worker -l info -c 4 -Q celery,recordings,dvr,default
|
||||
exec uv run celery -A dispatcharr worker -l info -c 4
|
||||
EOF
|
||||
chmod +x /opt/dispatcharr/start-celery.sh
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ update_os
|
||||
|
||||
PORTAINER_AGENT_LATEST_VERSION=$(get_latest_github_release "portainer/agent")
|
||||
|
||||
setup_docker
|
||||
|
||||
if prompt_confirm "${TAB3}Would you like to install Portainer (UI) via the community-scripts addon?" "n" 60; then
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)" <<<"y"
|
||||
read -r -p "${TAB3}Would you like to add Portainer (UI)? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
DOCKER_PORTAINER="true" setup_docker
|
||||
else
|
||||
setup_docker
|
||||
read -r -p "${TAB3}Would you like to install the Portainer Agent (for remote management)? <y/N> " prompt_agent
|
||||
if [[ ${prompt_agent,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Portainer Agent $PORTAINER_AGENT_LATEST_VERSION"
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: esatbayhan
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.firecrawl.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 install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
git \
|
||||
nftables \
|
||||
pkg-config \
|
||||
procps \
|
||||
python3 \
|
||||
rabbitmq-server \
|
||||
redis-server
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="22" NODE_MODULE="pnpm@11.4.0" setup_nodejs
|
||||
setup_go
|
||||
RUST_PROFILE="minimal" setup_rust
|
||||
PG_VERSION="17" PG_MODULES="cron" setup_postgresql
|
||||
|
||||
fetch_and_deploy_gh_release "firecrawl" "firecrawl/firecrawl" "tarball" "latest" "/opt/firecrawl"
|
||||
|
||||
msg_info "Configuring FDB"
|
||||
FDB_VERSION="$(awk -F= '/^ARG FDB_VERSION=/{print $2; exit}' /opt/firecrawl/apps/api/Dockerfile)"
|
||||
if [[ -z "$FDB_VERSION" ]]; then
|
||||
msg_error "FDB_VERSION pin not found in upstream Dockerfile"
|
||||
exit 1
|
||||
fi
|
||||
FDB_ARCH="$(get_system_arch)"
|
||||
[[ "$FDB_ARCH" == "arm64" ]] && FDB_ARCH="aarch64"
|
||||
fetch_and_deploy_gh_release "foundationdb-clients" "apple/foundationdb" "binary" "$FDB_VERSION" "/opt/foundationdb-clients" "foundationdb-clients_${FDB_VERSION}-1_${FDB_ARCH}.deb"
|
||||
msg_ok "Configured FDB"
|
||||
|
||||
PG_DB_NAME="firecrawl" PG_DB_USER="firecrawl" PG_DB_EXTENSIONS="pgcrypto,pg_cron" PG_DB_CREDS_FILE="/dev/null" setup_postgresql_db
|
||||
|
||||
msg_info "Configuring pg_cron"
|
||||
$STD runuser -u postgres -- psql -c "ALTER SYSTEM SET cron.use_background_workers = 'on';"
|
||||
systemctl restart postgresql
|
||||
until runuser -u postgres -- psql -c "SELECT 1;" &>/dev/null; do sleep 1; done
|
||||
msg_ok "Configured pg_cron"
|
||||
|
||||
msg_info "Configuring RabbitMQ"
|
||||
systemctl enable -q --now rabbitmq-server
|
||||
until rabbitmqctl status &>/dev/null; do sleep 1; done
|
||||
RABBITMQ_PASSWORD="$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c24)"
|
||||
$STD rabbitmqctl add_user firecrawl "$RABBITMQ_PASSWORD"
|
||||
$STD rabbitmqctl set_permissions -p / firecrawl ".*" ".*" ".*"
|
||||
msg_ok "Configured RabbitMQ"
|
||||
|
||||
systemctl enable -q --now redis-server
|
||||
|
||||
msg_info "Importing NuQ Schema"
|
||||
$STD runuser -u postgres -- psql -d firecrawl -f /opt/firecrawl/apps/nuq-postgres/nuq.sql
|
||||
$STD runuser -u postgres -- psql -d firecrawl -c "GRANT USAGE ON SCHEMA nuq TO firecrawl;"
|
||||
$STD runuser -u postgres -- psql -d firecrawl -c "GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA nuq TO firecrawl;"
|
||||
$STD runuser -u postgres -- psql -d firecrawl -c "GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA nuq TO firecrawl;"
|
||||
$STD runuser -u postgres -- psql -d firecrawl -c "ALTER DEFAULT PRIVILEGES IN SCHEMA nuq GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO firecrawl;"
|
||||
$STD runuser -u postgres -- psql -d firecrawl -c "ALTER DEFAULT PRIVILEGES IN SCHEMA nuq GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO firecrawl;"
|
||||
msg_ok "Imported NuQ Schema"
|
||||
|
||||
msg_info "Generating Configuration"
|
||||
cat <<EOF >/opt/firecrawl/.env
|
||||
ENV=local
|
||||
HOST=0.0.0.0
|
||||
PORT=3002
|
||||
USE_DB_AUTHENTICATION=false
|
||||
BULL_AUTH_KEY=$(openssl rand -hex 32)
|
||||
JWT_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
REDIS_URL=redis://127.0.0.1:6379
|
||||
REDIS_RATE_LIMIT_URL=redis://127.0.0.1:6379
|
||||
|
||||
PLAYWRIGHT_MICROSERVICE_URL=http://127.0.0.1:3000/scrape
|
||||
|
||||
POSTGRES_HOST=127.0.0.1
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USER=${PG_DB_USER}
|
||||
POSTGRES_PASSWORD=${PG_DB_PASS}
|
||||
POSTGRES_DB=${PG_DB_NAME}
|
||||
NUQ_DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
|
||||
NUQ_DATABASE_URL_LISTEN=postgresql://${PG_DB_USER}:${PG_DB_PASS}@127.0.0.1:5432/${PG_DB_NAME}
|
||||
|
||||
NUQ_BACKEND=pg
|
||||
NUQ_RABBITMQ_URL=amqp://firecrawl:${RABBITMQ_PASSWORD}@127.0.0.1:5672/%2f
|
||||
|
||||
WORKER_PORT=3005
|
||||
EXTRACT_WORKER_PORT=3004
|
||||
NUQ_WORKER_START_PORT=3006
|
||||
NUQ_WORKER_COUNT=5
|
||||
NUQ_PREFETCH_WORKER_PORT=3011
|
||||
NUQ_RECONCILER_WORKER_PORT=3012
|
||||
HARNESS_STARTUP_TIMEOUT_MS=60000
|
||||
|
||||
LOGGING_LEVEL=INFO
|
||||
MAX_CONCURRENT_PAGES=10
|
||||
ALLOW_LOCAL_WEBHOOKS=false
|
||||
BLOCK_MEDIA=false
|
||||
|
||||
OPENAI_API_KEY=
|
||||
OPENAI_BASE_URL=
|
||||
OLLAMA_BASE_URL=
|
||||
MODEL_NAME=
|
||||
MODEL_EMBEDDING_NAME=
|
||||
SEARXNG_ENDPOINT=
|
||||
SEARXNG_ENGINES=
|
||||
SEARXNG_CATEGORIES=
|
||||
PROXY_SERVER=
|
||||
PROXY_USERNAME=
|
||||
PROXY_PASSWORD=
|
||||
SELF_HOSTED_WEBHOOK_URL=
|
||||
SELF_HOSTED_WEBHOOK_HMAC_SECRET=
|
||||
EOF
|
||||
chmod 600 /opt/firecrawl/.env
|
||||
msg_ok "Generated Configuration"
|
||||
|
||||
msg_info "Building Go Library"
|
||||
cd /opt/firecrawl/apps/api/sharedLibs/go-html-to-md
|
||||
$STD go build -o libhtml-to-markdown.so -buildmode=c-shared html-to-markdown.go
|
||||
msg_ok "Built Go Library"
|
||||
|
||||
msg_info "Building Firecrawl API"
|
||||
cd /opt/firecrawl/apps/api
|
||||
$STD pnpm install --frozen-lockfile
|
||||
$STD pnpm build
|
||||
CI=true $STD pnpm prune --prod --ignore-scripts
|
||||
msg_ok "Built Firecrawl API"
|
||||
|
||||
msg_info "Building Playwright Service"
|
||||
cd /opt/firecrawl/apps/playwright-service-ts
|
||||
$STD npm install
|
||||
$STD npx playwright install chromium --with-deps
|
||||
$STD npm run build
|
||||
$STD npm prune --omit=dev
|
||||
msg_ok "Built Playwright Service"
|
||||
|
||||
msg_info "Creating Services"
|
||||
cat <<EOF >/etc/systemd/system/firecrawl-playwright.service
|
||||
[Unit]
|
||||
Description=Firecrawl Playwright Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/firecrawl/apps/playwright-service-ts
|
||||
EnvironmentFile=/opt/firecrawl/.env
|
||||
Environment=PORT=3000
|
||||
# /opt/firecrawl/.env also contains the API PORT=3002; force Playwright's private port here.
|
||||
ExecStart=/usr/bin/env PORT=3000 /usr/bin/node /opt/firecrawl/apps/playwright-service-ts/dist/api.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat <<EOF >/etc/systemd/system/firecrawl.service
|
||||
[Unit]
|
||||
Description=Firecrawl API and Workers
|
||||
After=network.target postgresql.service redis-server.service rabbitmq-server.service firecrawl-playwright.service
|
||||
Requires=postgresql.service redis-server.service rabbitmq-server.service firecrawl-playwright.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/firecrawl/apps/api
|
||||
EnvironmentFile=/opt/firecrawl/.env
|
||||
Environment=NODE_ENV=production
|
||||
# Upstream uses --start-docker to skip install/build and start compiled node dist entrypoints.
|
||||
ExecStart=/usr/bin/node /opt/firecrawl/apps/api/dist/src/harness.js --start-docker
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now firecrawl-playwright
|
||||
systemctl enable -q --now firecrawl
|
||||
msg_ok "Created Services"
|
||||
|
||||
msg_info "Configuring Firewall"
|
||||
cat <<'EOF' >/etc/nftables.conf
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
flush ruleset
|
||||
|
||||
table inet firecrawl_filter {
|
||||
chain input {
|
||||
type filter hook input priority 0; policy drop;
|
||||
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr icmpv6 accept
|
||||
udp sport 67 udp dport 68 accept
|
||||
udp sport 547 udp dport 546 accept
|
||||
|
||||
tcp dport { 22, 3002 } accept
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
systemctl enable -q nftables
|
||||
systemctl restart nftables
|
||||
msg_ok "Configured Firewall"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -32,8 +32,7 @@ get_latest_release() {
|
||||
|
||||
CORE_LATEST_VERSION=$(get_latest_release "home-assistant/core")
|
||||
|
||||
setup_docker
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)" <<<"y"
|
||||
DOCKER_PORTAINER="true" setup_docker
|
||||
|
||||
msg_info "Pulling Home Assistant $CORE_LATEST_VERSION Image"
|
||||
$STD docker pull ghcr.io/home-assistant/home-assistant:stable
|
||||
|
||||
@@ -312,7 +312,7 @@ ML_DIR="${APP_DIR}/machine-learning"
|
||||
GEO_DIR="${INSTALL_DIR}/geodata"
|
||||
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
|
||||
|
||||
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.1.0" "$SRC_DIR"
|
||||
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.3" "$SRC_DIR"
|
||||
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
|
||||
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||
NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs
|
||||
@@ -429,7 +429,6 @@ msg_info "Installing GeoNames data"
|
||||
cd "$GEO_DIR"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/admin1CodesASCII.txt" "admin1CodesASCII.txt"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/admin2Codes.txt" "admin2Codes.txt"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/countryInfo.txt" "countryInfo.txt"
|
||||
curl_with_retry "https://download.geonames.org/export/dump/cities500.zip" "cities500.zip"
|
||||
curl_with_retry "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson" "ne_10m_admin_0_countries.geojson"
|
||||
unzip -q cities500.zip
|
||||
|
||||
@@ -25,8 +25,7 @@ $STD apt install -y \
|
||||
rrdtool \
|
||||
snmp \
|
||||
snmpd \
|
||||
whois \
|
||||
ipmitool
|
||||
whois
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Installing Python Dependencies"
|
||||
|
||||
@@ -19,16 +19,12 @@ $STD apt install -y \
|
||||
git-core \
|
||||
mediainfo
|
||||
|
||||
cat <<EOF >/etc/apt/sources.list.d/non-free.sources
|
||||
Types: deb
|
||||
URIs: https://deb.debian.org/debian
|
||||
Suites: trixie
|
||||
Components: non-free non-free-firmware
|
||||
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
|
||||
cat <<EOF >/etc/apt/sources.list.d/non-free.list
|
||||
deb https://deb.debian.org/debian trixie main contrib non-free non-free-firmware
|
||||
EOF
|
||||
$STD apt update
|
||||
$STD apt install -y unrar
|
||||
rm /etc/apt/sources.list.d/non-free.sources
|
||||
rm /etc/apt/sources.list.d/non-free.list
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Installing Medusa"
|
||||
|
||||
@@ -71,6 +71,12 @@ msg_ok "Created Service"
|
||||
msg_info "Starting Service"
|
||||
systemctl enable -q --now nginx-ui
|
||||
rm -rf /etc/nginx/sites-enabled/default
|
||||
sleep 3
|
||||
cat <<EOF >~/nginx-ui.creds
|
||||
Nginx UI Install Secret: $(cat /usr/local/etc/nginx-ui/.install_secret 2>/dev/null)
|
||||
Valid for 10 minutes after service start, then removed.
|
||||
New secret: systemctl restart nginx-ui && cat /usr/local/etc/nginx-ui/.install_secret
|
||||
EOF
|
||||
msg_ok "Started Service"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/vrtmrz/obsidian-livesync | https://couchdb.apache.org/
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
setup_deb822_repo \
|
||||
"couchdb" \
|
||||
"https://couchdb.apache.org/repo/keys.asc" \
|
||||
"https://apache.jfrog.io/artifactory/couchdb-deb/" \
|
||||
"$(get_os_info codename)" \
|
||||
"main"
|
||||
|
||||
msg_info "Installing CouchDB"
|
||||
COUCHDB_ADMIN_USER="admin"
|
||||
COUCHDB_PASSWORD="$(openssl rand -hex 24)"
|
||||
COUCHDB_COOKIE="$(openssl rand -hex 16)"
|
||||
|
||||
cat <<EOF | debconf-set-selections
|
||||
couchdb couchdb/mode select standalone
|
||||
couchdb couchdb/mode seen true
|
||||
couchdb couchdb/bindaddress string 0.0.0.0
|
||||
couchdb couchdb/bindaddress seen true
|
||||
couchdb couchdb/cookie string ${COUCHDB_COOKIE}
|
||||
couchdb couchdb/cookie seen true
|
||||
couchdb couchdb/adminpass password ${COUCHDB_PASSWORD}
|
||||
couchdb couchdb/adminpass seen true
|
||||
couchdb couchdb/adminpass_again password ${COUCHDB_PASSWORD}
|
||||
couchdb couchdb/adminpass_again seen true
|
||||
EOF
|
||||
DEBIAN_FRONTEND=noninteractive $STD apt-get install -y couchdb
|
||||
|
||||
cat <<EOF >/root/.couchdb.credentials
|
||||
COUCHDB_ADMIN_USER="${COUCHDB_ADMIN_USER}"
|
||||
COUCHDB_ADMIN_PASSWORD="${COUCHDB_PASSWORD}"
|
||||
COUCHDB_COOKIE="${COUCHDB_COOKIE}"
|
||||
EOF
|
||||
msg_ok "Installed CouchDB"
|
||||
|
||||
msg_info "Configuring CouchDB"
|
||||
mkdir -p /opt/couchdb/etc/local.d /opt/obsidian-livesync
|
||||
cat <<EOF >/opt/couchdb/etc/local.d/obsidian-livesync.ini
|
||||
[couchdb]
|
||||
single_node = true
|
||||
max_document_size = 50000000
|
||||
|
||||
[admins]
|
||||
admin = ${COUCHDB_PASSWORD}
|
||||
|
||||
[chttpd]
|
||||
bind_address = 0.0.0.0
|
||||
port = 5984
|
||||
max_http_request_size = 4294967296
|
||||
|
||||
[chttpd_auth]
|
||||
require_valid_user = true
|
||||
|
||||
[httpd]
|
||||
enable_cors = true
|
||||
WWW-Authenticate = Basic realm="couchdb"
|
||||
|
||||
[cors]
|
||||
credentials = true
|
||||
origins = app://obsidian.md,capacitor://localhost,http://localhost
|
||||
headers = accept, authorization, content-type, origin, referer
|
||||
methods = GET, PUT, POST, HEAD, DELETE
|
||||
max_age = 3600
|
||||
EOF
|
||||
cat <<EOF >/opt/obsidian-livesync/.env
|
||||
COUCHDB_URL=http://${LOCAL_IP}:5984
|
||||
COUCHDB_USER=admin
|
||||
COUCHDB_PASSWORD=${COUCHDB_PASSWORD}
|
||||
COUCHDB_DATABASE=obsidiannotes
|
||||
EOF
|
||||
chmod 600 /opt/obsidian-livesync/.env
|
||||
msg_ok "Configured CouchDB"
|
||||
|
||||
msg_info "Creating LiveSync Database"
|
||||
systemctl enable -q couchdb
|
||||
systemctl restart couchdb
|
||||
for _ in {1..30}; do
|
||||
curl -fsS -u "admin:${COUCHDB_PASSWORD}" -X PUT http://127.0.0.1:5984/obsidiannotes >/dev/null 2>&1 && break
|
||||
sleep 1
|
||||
done
|
||||
msg_ok "Created LiveSync Database"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -1,59 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/diegosouzapw/OmniRoute
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
|
||||
msg_info "Installing OmniRoute"
|
||||
$STD npm install -g omniroute@latest
|
||||
msg_ok "Installed OmniRoute"
|
||||
|
||||
msg_info "Configuring OmniRoute"
|
||||
mkdir -p /opt/omniroute
|
||||
cat <<EOF >/opt/omniroute/.env
|
||||
JWT_SECRET=$(openssl rand -base64 48)
|
||||
API_KEY_SECRET=$(openssl rand -hex 32)
|
||||
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
|
||||
STORAGE_ENCRYPTION_KEY_VERSION=v1
|
||||
INITIAL_PASSWORD=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-20)
|
||||
PORT=20128
|
||||
OMNIROUTE_SERVER_HOST=0.0.0.0
|
||||
EOF
|
||||
chmod 600 /opt/omniroute/.env
|
||||
msg_ok "Configured OmniRoute"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/omniroute.service
|
||||
[Unit]
|
||||
Description=OmniRoute AI Gateway
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/omniroute
|
||||
Environment=DATA_DIR=/opt/omniroute
|
||||
ExecStart=/usr/bin/omniroute
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now omniroute
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -64,7 +64,7 @@ $STD sudo -u cool coolconfig set-admin-password --user=admin --password="$COOLPA
|
||||
echo "$COOLPASS" >~/.coolpass
|
||||
msg_ok "Installed Collabora Online"
|
||||
|
||||
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.4.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
|
||||
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.3.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
|
||||
mv /usr/bin/OpenCloud /usr/bin/opencloud
|
||||
|
||||
msg_info "Configuring OpenCloud"
|
||||
|
||||
@@ -26,7 +26,7 @@ create_self_signed_cert
|
||||
|
||||
setup_deb822_repo \
|
||||
"passbolt" \
|
||||
"https://download.passbolt.com/pub.key" \
|
||||
"https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x3D1A0346C8E1802F774AEF21DE8B853FC155581D" \
|
||||
"https://download.passbolt.com/ce/debian" \
|
||||
"buster" \
|
||||
"stable"
|
||||
|
||||
@@ -22,13 +22,12 @@ $STD apt install -y \
|
||||
pkg-config
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
RUBY_VERSION="4.0.5" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
|
||||
|
||||
fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball"
|
||||
|
||||
RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
|
||||
|
||||
msg_info "Installing Gem Dependencies"
|
||||
cd /opt/passwordpusher
|
||||
$STD bundle config set --local without 'development test'
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/PegaProx/project-pegaprox
|
||||
|
||||
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 sshpass
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
PYTHON_VERSION="3.12" setup_uv
|
||||
|
||||
fetch_and_deploy_gh_release "pegaprox" "PegaProx/project-pegaprox" "tarball"
|
||||
|
||||
msg_info "Setting up Python Environment"
|
||||
$STD uv venv --python 3.12 /opt/pegaprox/venv
|
||||
$STD uv pip install --python /opt/pegaprox/venv/bin/python -r /opt/pegaprox/requirements.txt
|
||||
msg_ok "Set up Python Environment"
|
||||
|
||||
msg_info "Generating Master Key"
|
||||
mkdir -p /etc/pegaprox
|
||||
cat <<EOF >/etc/pegaprox/secret.key
|
||||
$(openssl rand -base64 32 | tr '+/' '-_')
|
||||
EOF
|
||||
chmod 600 /etc/pegaprox/secret.key
|
||||
msg_ok "Generated Master Key"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/pegaprox.service
|
||||
[Unit]
|
||||
Description=PegaProx - Multi-Cluster Proxmox VE Management
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/pegaprox
|
||||
ExecStart=/opt/pegaprox/venv/bin/python /opt/pegaprox/pegaprox_multi_cluster.py
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now pegaprox
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -37,8 +37,6 @@ $STD apt install -y \
|
||||
redis-server \
|
||||
redis-tools \
|
||||
p7zip-full \
|
||||
7zip-standalone \
|
||||
libarchive-tools \
|
||||
tzdata
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Pin: version ${RELEASE}
|
||||
Pin-Priority: 1001
|
||||
EOF
|
||||
$STD apt install -y salt-master
|
||||
echo "${RELEASE}" >~/.salt
|
||||
echo "${RELEASE}" >/~.salt
|
||||
msg_ok "Installed Salt"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -18,7 +18,7 @@ $STD apt install -y gcc
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
setup_go
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
fetch_and_deploy_gh_release "watcharr" "sbondCo/Watcharr" "tarball"
|
||||
|
||||
msg_info "Setup Watcharr"
|
||||
|
||||
@@ -10,29 +10,8 @@ fi
|
||||
# must write local failure artifacts instead of talking to the telemetry API
|
||||
# (the host is the single telemetry reporter).
|
||||
export TELEMETRY_CONTEXT="container"
|
||||
# A freshly booted container may not have DNS up yet. `source <(curl ...)` hides
|
||||
# curl's exit code, so a failed download would silently source an empty stream.
|
||||
_bootstrap_die() {
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "$1"
|
||||
else
|
||||
echo "FATAL: $1" >&2
|
||||
fi
|
||||
exit 115
|
||||
}
|
||||
|
||||
_bootstrap_source() {
|
||||
local url="$1" probe="$2" content
|
||||
content=$(curl -fsSL --connect-timeout 10 --retry 5 --retry-connrefused --retry-delay 2 "$url") ||
|
||||
_bootstrap_die "Failed to download ${url##*/}"
|
||||
source /dev/stdin <<<"$content"
|
||||
declare -f "$probe" >/dev/null 2>&1 ||
|
||||
_bootstrap_die "${url##*/} loaded but incomplete (missing ${probe})"
|
||||
}
|
||||
|
||||
_FUNC_BASE="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc"
|
||||
_bootstrap_source "$_FUNC_BASE/core.func" load_functions
|
||||
_bootstrap_source "$_FUNC_BASE/error_handler.func" catch_errors
|
||||
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/error_handler.func)
|
||||
load_functions
|
||||
catch_errors
|
||||
|
||||
@@ -126,7 +105,7 @@ network_check() {
|
||||
fi
|
||||
|
||||
if [[ $ipv4_connected == false ]]; then
|
||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt </dev/tty
|
||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||
else
|
||||
|
||||
+25
-186
@@ -88,38 +88,19 @@ variables() {
|
||||
fi
|
||||
}
|
||||
|
||||
# `source <(curl ...)` hides the download exit code, so a failed fetch would
|
||||
# silently source an empty stream and leave the helpers undefined.
|
||||
_bootstrap_die() {
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "$1"
|
||||
else
|
||||
echo "FATAL: $1" >&2
|
||||
fi
|
||||
exit 115
|
||||
}
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
||||
|
||||
_bootstrap_source() {
|
||||
local url="$1" probe="$2" content=""
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
content=$(curl -fsSL --connect-timeout 10 --retry 5 --retry-connrefused --retry-delay 2 "$url") || content=""
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
content=$(wget -qO- --tries=5 --timeout=10 "$url") || content=""
|
||||
else
|
||||
_bootstrap_die "Neither curl nor wget available"
|
||||
fi
|
||||
[[ -n "$content" ]] || _bootstrap_die "Failed to download ${url##*/}"
|
||||
source /dev/stdin <<<"$content"
|
||||
declare -f "$probe" >/dev/null 2>&1 ||
|
||||
_bootstrap_die "${url##*/} loaded but incomplete (missing ${probe})"
|
||||
}
|
||||
|
||||
_FUNC_BASE="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc"
|
||||
_bootstrap_source "$_FUNC_BASE/api.func" post_to_api
|
||||
_bootstrap_source "$_FUNC_BASE/core.func" load_functions
|
||||
_bootstrap_source "$_FUNC_BASE/error_handler.func" catch_errors
|
||||
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/error_handler.func)
|
||||
load_functions
|
||||
catch_errors
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
source <(wget -qO- https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(wget -qO- https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
load_functions
|
||||
catch_errors
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# SECTION 2: PRE-FLIGHT CHECKS & SYSTEM VALIDATION
|
||||
@@ -1130,7 +1111,6 @@ base_settings() {
|
||||
|
||||
APT_CACHER=${var_apt_cacher:-""}
|
||||
APT_CACHER_IP=${var_apt_cacher_ip:-""}
|
||||
INHERIT_HOST_CA="${var_inherit_host_ca:-no}"
|
||||
|
||||
# Runtime check: Verify APT cacher is reachable if configured
|
||||
if [[ -n "$APT_CACHER_IP" && "$APT_CACHER" == "yes" ]]; then
|
||||
@@ -1213,7 +1193,7 @@ load_vars_file() {
|
||||
|
||||
# Allowed var_* keys
|
||||
local VAR_WHITELIST=(
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_keyctl
|
||||
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
|
||||
var_net var_nesting var_ns var_os var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
|
||||
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
|
||||
@@ -1410,12 +1390,6 @@ load_vars_file() {
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_inherit_host_ca)
|
||||
if [[ "$var_val" != "yes" && "$var_val" != "no" && "$var_val" != "auto" ]]; then
|
||||
msg_warn "Invalid host CA inheritance value '$var_val' in $file (must be yes/no/auto), ignoring"
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
var_container_storage | var_template_storage)
|
||||
# Validate that the storage exists and is active on the current node
|
||||
local _storage_status
|
||||
@@ -1455,7 +1429,7 @@ default_var_settings() {
|
||||
# Allowed var_* keys (alphabetically sorted)
|
||||
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
||||
local VAR_WHITELIST=(
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_keyctl
|
||||
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
|
||||
var_net var_nesting var_ns var_os var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
|
||||
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
|
||||
@@ -1538,7 +1512,6 @@ var_ssh=no
|
||||
# HTTP/HTTPS proxy (optional - for networks requiring a proxy)
|
||||
# var_http_proxy=http://proxy.local:8080
|
||||
# var_http_no_proxy=localhost,127.0.0.1,.local
|
||||
# var_inherit_host_ca=no
|
||||
|
||||
# Features/Tags/verbosity
|
||||
var_fuse=no
|
||||
@@ -1639,7 +1612,7 @@ get_app_defaults_path() {
|
||||
if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then
|
||||
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
|
||||
declare -ag VAR_WHITELIST=(
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_inherit_host_ca var_keyctl
|
||||
var_apt_cacher var_apt_cacher_ip var_brg var_cpu var_disk var_fuse var_github_token var_gpu var_http_no_proxy var_http_proxy var_keyctl
|
||||
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu
|
||||
var_net var_nesting var_ns var_os var_protection var_pw var_ram var_tags var_timezone var_tun var_unprivileged
|
||||
var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
|
||||
@@ -1789,7 +1762,6 @@ _build_current_app_vars_tmp() {
|
||||
_apt_cacher_ip="${APT_CACHER_IP:-}"
|
||||
_http_proxy="${HTTP_PROXY:-${var_http_proxy:-}}"
|
||||
_http_no_proxy="${HTTP_NO_PROXY:-${var_http_no_proxy:-}}"
|
||||
_inherit_host_ca="${INHERIT_HOST_CA:-${var_inherit_host_ca:-no}}"
|
||||
_fuse="${ENABLE_FUSE:-no}"
|
||||
_tun="${ENABLE_TUN:-no}"
|
||||
_gpu="${ENABLE_GPU:-no}"
|
||||
@@ -1843,7 +1815,6 @@ _build_current_app_vars_tmp() {
|
||||
[ -n "$_apt_cacher_ip" ] && echo "var_apt_cacher_ip=$(_sanitize_value "$_apt_cacher_ip")"
|
||||
[ -n "$_http_proxy" ] && echo "var_http_proxy=$(_sanitize_value "$_http_proxy")"
|
||||
[ -n "$_http_no_proxy" ] && echo "var_http_no_proxy=$(_sanitize_value "$_http_no_proxy")"
|
||||
[ -n "$_inherit_host_ca" ] && echo "var_inherit_host_ca=$(_sanitize_value "$_inherit_host_ca")"
|
||||
|
||||
[ -n "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
|
||||
[ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")"
|
||||
@@ -2008,7 +1979,7 @@ advanced_settings() {
|
||||
TAGS="community-script${var_tags:+;${var_tags}}"
|
||||
fi
|
||||
local STEP=1
|
||||
local MAX_STEP=31
|
||||
local MAX_STEP=30
|
||||
|
||||
# Store values for back navigation - inherit from var_* app defaults
|
||||
local _ct_type="${var_unprivileged:-1}"
|
||||
@@ -2030,7 +2001,6 @@ advanced_settings() {
|
||||
local _apt_cacher_ip="${var_apt_cacher_ip:-}"
|
||||
local _http_proxy="${var_http_proxy:-}"
|
||||
local _http_no_proxy="${var_http_no_proxy:-}"
|
||||
local _inherit_host_ca="${var_inherit_host_ca:-no}"
|
||||
local _mtu="${var_mtu:-}"
|
||||
local _sd="${var_searchdomain:-}"
|
||||
local _ns="${var_ns:-}"
|
||||
@@ -2860,47 +2830,9 @@ advanced_settings() {
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 25: Host CA Inheritance
|
||||
# STEP 25: Container Timezone
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
25)
|
||||
local host_ca_count=0
|
||||
local host_ca_dir="/usr/local/share/ca-certificates"
|
||||
local cert
|
||||
shopt -s nullglob
|
||||
for cert in "$host_ca_dir"/*.crt; do
|
||||
host_ca_count=$((host_ca_count + 1))
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
if [[ $host_ca_count -eq 0 ]]; then
|
||||
_inherit_host_ca="no"
|
||||
((STEP++))
|
||||
continue
|
||||
fi
|
||||
|
||||
local host_ca_default_flag="--defaultno"
|
||||
[[ "$_inherit_host_ca" == "yes" ]] && host_ca_default_flag=""
|
||||
if whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "HOST CA INHERITANCE" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
$host_ca_default_flag \
|
||||
--yesno "\nInherit host CA certificates into this container?\n\nDetected on host: ${host_ca_count} certificate(s) in:\n${host_ca_dir}\n\nRecommended for private PKI / TLS-inspection environments.\n\n(App default: ${var_inherit_host_ca:-no})" 16 72; then
|
||||
_inherit_host_ca="yes"
|
||||
else
|
||||
if [ $? -eq 1 ]; then
|
||||
_inherit_host_ca="no"
|
||||
else
|
||||
((STEP--))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
((STEP++))
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 26: Container Timezone
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
26)
|
||||
local tz_hint="$_ct_timezone"
|
||||
[[ -z "$tz_hint" ]] && tz_hint="(empty - will use host timezone)"
|
||||
|
||||
@@ -2923,9 +2855,9 @@ advanced_settings() {
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 27: Container Protection
|
||||
# STEP 26: Container Protection
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
27)
|
||||
26)
|
||||
local protect_default_flag="--defaultno"
|
||||
[[ "$_protect_ct" == "yes" || "$_protect_ct" == "1" ]] && protect_default_flag=""
|
||||
|
||||
@@ -2947,9 +2879,9 @@ advanced_settings() {
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 28: Device Node Creation (mknod)
|
||||
# STEP 27: Device Node Creation (mknod)
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
28)
|
||||
27)
|
||||
local mknod_default_flag="--defaultno"
|
||||
[[ "$_enable_mknod" == "1" ]] && mknod_default_flag=""
|
||||
|
||||
@@ -2971,9 +2903,9 @@ advanced_settings() {
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 29: Mount Filesystems
|
||||
# STEP 28: Mount Filesystems
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
29)
|
||||
28)
|
||||
local mount_hint=""
|
||||
[[ -n "$_mount_fs" ]] && mount_hint="$_mount_fs" || mount_hint="(none)"
|
||||
|
||||
@@ -2994,9 +2926,9 @@ advanced_settings() {
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 30: Optional host-side post-install hook (path on the Proxmox HOST)
|
||||
# STEP 29: Optional host-side post-install hook (path on the Proxmox HOST)
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
30)
|
||||
29)
|
||||
local _hook_prompt="Optional: absolute path to a *.sh file ON THE PROXMOX HOST.
|
||||
|
||||
It runs as root on the HOST (NOT in the LXC) after the container
|
||||
@@ -3046,9 +2978,9 @@ Leave empty to skip."
|
||||
;;
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# STEP 31: Verbose Mode & Confirmation
|
||||
# STEP 30: Verbose Mode & Confirmation
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
31)
|
||||
30)
|
||||
local verbose_default_flag="--defaultno"
|
||||
[[ "$_verbose" == "yes" ]] && verbose_default_flag=""
|
||||
|
||||
@@ -3077,7 +3009,6 @@ Leave empty to skip."
|
||||
local apt_display="${_apt_cacher:-no}"
|
||||
[[ "$_apt_cacher" == "yes" && -n "$_apt_cacher_ip" ]] && apt_display="$_apt_cacher_ip"
|
||||
local http_proxy_display="${_http_proxy:-(none)}"
|
||||
local inherit_ca_display="${_inherit_host_ca:-no}"
|
||||
|
||||
local post_install_display="${_post_install:-(none)}"
|
||||
local post_install_warn=""
|
||||
@@ -3108,7 +3039,6 @@ Advanced:
|
||||
Timezone: $tz_display
|
||||
APT Cacher: $apt_display
|
||||
HTTP Proxy: $http_proxy_display
|
||||
Inherit Host CAs: $inherit_ca_display
|
||||
Verbose: $_verbose
|
||||
Post-Install Script: ${post_install_display}${post_install_warn}"
|
||||
|
||||
@@ -3154,7 +3084,6 @@ Advanced:
|
||||
APT_CACHER_IP="$_apt_cacher_ip"
|
||||
HTTP_PROXY="$_http_proxy"
|
||||
HTTP_NO_PROXY="$_http_no_proxy"
|
||||
INHERIT_HOST_CA="$_inherit_host_ca"
|
||||
VERBOSE="$_verbose"
|
||||
var_post_install="$_post_install"
|
||||
|
||||
@@ -3173,7 +3102,6 @@ Advanced:
|
||||
var_sdn_vnet="$_sdn_vnet"
|
||||
var_http_proxy="$_http_proxy"
|
||||
var_http_no_proxy="$_http_no_proxy"
|
||||
var_inherit_host_ca="$_inherit_host_ca"
|
||||
|
||||
# Format optional values
|
||||
[[ -n "$_mtu" ]] && MTU=",mtu=$_mtu" || MTU=""
|
||||
@@ -3917,7 +3845,7 @@ run_addon_updates() {
|
||||
name="${a##*/update_}"
|
||||
printf 'Do you also want to update addon "%s"? (y/N) [60s]: ' "$name"
|
||||
ans=""
|
||||
if read -r -t 60 ans </dev/tty; then :; else echo; fi
|
||||
if read -r -t 60 ans; then :; else echo; fi
|
||||
case "${ans,,}" in
|
||||
y | yes)
|
||||
bash "$a" || msg_warn "Addon update for $name failed (rc=$?)"
|
||||
@@ -4213,83 +4141,6 @@ EOF
|
||||
msg_ok "Applied HTTP proxy in container"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# _apply_host_ca_certs_in_container()
|
||||
#
|
||||
# - Copies administrator-provided CA certificates from the Proxmox host into the
|
||||
# container before base package bootstrap
|
||||
# - Source: /usr/local/share/ca-certificates/*.crt (Debian convention)
|
||||
# - Refreshes the container trust store when update-ca-certificates is available
|
||||
# - No-op when no host certificates are present; failures are non-fatal
|
||||
# ------------------------------------------------------------------------------
|
||||
_apply_host_ca_certs_in_container() {
|
||||
local host_ca_dir="/usr/local/share/ca-certificates"
|
||||
[[ -z "${CTID:-}" ]] && return 0
|
||||
local inherit_host_ca="${INHERIT_HOST_CA:-${var_inherit_host_ca:-no}}"
|
||||
|
||||
local -a host_certs=()
|
||||
local cert
|
||||
shopt -s nullglob
|
||||
for cert in "$host_ca_dir"/*.crt; do
|
||||
host_certs+=("$cert")
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
[[ ${#host_certs[@]} -eq 0 ]] && return 0
|
||||
|
||||
# Opt-in only: copy host CA certs solely when explicitly enabled.
|
||||
# Any other value (no/auto/unset) is a silent no-op to preserve LXC isolation.
|
||||
case "${inherit_host_ca,,}" in
|
||||
yes | true | 1 | on) ;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
msg_info "Inheriting host CA certificates into container"
|
||||
|
||||
local found=${#host_certs[@]}
|
||||
local copied=0
|
||||
local skipped=0
|
||||
local cert_name
|
||||
|
||||
pct exec "$CTID" -- mkdir -p /usr/local/share/ca-certificates >/dev/null 2>&1 || {
|
||||
msg_warn "Failed to create CA certificate directory in container"
|
||||
return 0
|
||||
}
|
||||
|
||||
for cert in "${host_certs[@]}"; do
|
||||
cert_name="$(basename "$cert")"
|
||||
if [[ ! -r "$cert" || "$cert_name" != *.crt ]]; then
|
||||
msg_warn "Skipping invalid or unreadable host CA certificate: ${cert_name}"
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if pct push "$CTID" "$cert" "/usr/local/share/ca-certificates/${cert_name}" >/dev/null 2>&1; then
|
||||
pct exec "$CTID" -- chmod 644 "/usr/local/share/ca-certificates/${cert_name}" >/dev/null 2>&1 || true
|
||||
copied=$((copied + 1))
|
||||
else
|
||||
msg_warn "Failed to push host CA certificate: ${cert_name}"
|
||||
skipped=$((skipped + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $copied -eq 0 ]]; then
|
||||
msg_warn "No host CA certificates were copied (${found} found, ${skipped} skipped)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local refresh_shell="bash"
|
||||
[[ "$var_os" == "alpine" ]] && refresh_shell="ash"
|
||||
|
||||
if pct exec "$CTID" -- "$refresh_shell" -c 'command -v update-ca-certificates >/dev/null 2>&1 && update-ca-certificates' >/dev/null 2>&1; then
|
||||
msg_ok "Inherited ${copied} host CA certificate(s) and updated trust store (${skipped} skipped)"
|
||||
else
|
||||
msg_warn "Copied ${copied} host CA certificate(s), but trust store update failed or update-ca-certificates is unavailable (${skipped} skipped)"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# build_container()
|
||||
#
|
||||
@@ -4919,7 +4770,6 @@ EOF
|
||||
local install_exit_code=0
|
||||
|
||||
_apply_http_proxy_in_container
|
||||
_apply_host_ca_certs_in_container
|
||||
|
||||
# Continue with standard container setup
|
||||
if [ "$var_os" == "alpine" ]; then
|
||||
@@ -5200,16 +5050,6 @@ EOF
|
||||
# TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop)
|
||||
trap '' TSTP TTIN TTOU
|
||||
|
||||
# lxc-attach takes the controlling terminal while the install runs and does
|
||||
# not hand it back, leaving us in a background process group. Reading from
|
||||
# the terminal then returns EIO instead of blocking, because SIGTTIN is
|
||||
# ignored above - so every recovery prompt fails before the user can answer.
|
||||
# Redirecting to /dev/tty does not help: the rule applies to the terminal,
|
||||
# not the file descriptor. Claim the foreground group back; SIGTTOU is
|
||||
# ignored too, so tcsetpgrp() succeeds instead of stopping us. No-op when we
|
||||
# already are in the foreground. perl is a hard dependency of Proxmox VE.
|
||||
perl -e 'use POSIX; open(my $t, "+<", "/dev/tty") or exit 1; POSIX::tcsetpgrp(fileno($t), getpgrp()) or exit 1;' 2>/dev/null || true
|
||||
|
||||
msg_error "Installation failed in container ${CTID} (exit code: ${install_exit_code})"
|
||||
|
||||
# Copy install log from container BEFORE API call so get_error_text() can read it
|
||||
@@ -5729,7 +5569,6 @@ EOF
|
||||
# read itself failed (e.g. broken/closed stdin, I/O error) rather than
|
||||
# timing out - don't guess and destroy the container on a read we
|
||||
# couldn't actually capture; keep it since that's the reversible choice.
|
||||
while read -r -t 0.1 -n 1 _ </dev/tty 2>/dev/null; do :; done
|
||||
echo ""
|
||||
msg_error "Could not read your response (stdin error) - keeping container ${CTID} for safety."
|
||||
msg_error "Remove it manually if not needed: pct destroy ${CTID}"
|
||||
|
||||
+7
-77
@@ -299,72 +299,6 @@ root_check() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# on_pve_host()
|
||||
#
|
||||
# - Returns 0 when executed on a Proxmox VE node, 1 otherwise
|
||||
# - Cheap probe used by the guards below; never exits on its own
|
||||
# ------------------------------------------------------------------------------
|
||||
on_pve_host() {
|
||||
command -v pveversion &>/dev/null
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# require_pve_host()
|
||||
#
|
||||
# - Guard for tools that drive the node itself (pct/pveam/pvesm/pvesh/qm)
|
||||
# - Aborts when not on a PVE node, then validates the PVE version
|
||||
# ------------------------------------------------------------------------------
|
||||
require_pve_host() {
|
||||
if ! on_pve_host; then
|
||||
msg_error "${APP:-This script} must be run on the Proxmox VE host."
|
||||
msg_error "Proxmox tooling (pct/pveam/pvesm/qm) is not available here."
|
||||
exit 232
|
||||
fi
|
||||
pve_check
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# confirm_not_pve_host()
|
||||
#
|
||||
# - Guard for tools that belong inside an LXC/VM but would technically run
|
||||
# on the node as well
|
||||
# - Warns and asks for confirmation instead of hard-failing
|
||||
# ------------------------------------------------------------------------------
|
||||
confirm_not_pve_host() {
|
||||
on_pve_host || return 0
|
||||
|
||||
msg_error "Running on the Proxmox VE host is NOT recommended!"
|
||||
msg_error "${APP:-This script} is meant to be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB:- }Continue anyway? (y/N): "
|
||||
local confirm
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on the Proxmox VE host at your own risk!"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# require_debian_like()
|
||||
#
|
||||
# - Guard for addons that have no Alpine code path
|
||||
# - Aborts early instead of failing halfway through with apt/systemd errors
|
||||
# ------------------------------------------------------------------------------
|
||||
require_debian_like() {
|
||||
if is_alpine; then
|
||||
msg_error "${APP:-This script} does not support Alpine Linux."
|
||||
msg_error "Please use a Debian or Ubuntu based LXC container."
|
||||
exit 238
|
||||
fi
|
||||
if ! command -v apt-get &>/dev/null; then
|
||||
msg_error "${APP:-This script} requires a Debian or Ubuntu based system."
|
||||
exit 238
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# pve_check()
|
||||
#
|
||||
@@ -374,10 +308,6 @@ require_debian_like() {
|
||||
# ------------------------------------------------------------------------------
|
||||
pve_check() {
|
||||
local PVE_VER
|
||||
if ! on_pve_host; then
|
||||
msg_error "${APP:-This script} must be run on the Proxmox VE host."
|
||||
exit 232
|
||||
fi
|
||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||
|
||||
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||
@@ -824,7 +754,7 @@ msg_info() {
|
||||
# Pause mode: Wait for Enter after each step
|
||||
if [[ "${DEV_MODE_PAUSE:-false}" == "true" ]]; then
|
||||
echo -en "\n${YWB}[PAUSE]${CL} Press Enter to continue..." >&2
|
||||
read -r </dev/tty
|
||||
read -r
|
||||
fi
|
||||
return
|
||||
fi
|
||||
@@ -839,7 +769,7 @@ msg_info() {
|
||||
if [[ "${DEV_MODE_PAUSE:-false}" == "true" ]]; then
|
||||
stop_spinner
|
||||
echo -en "\n${YWB}[PAUSE]${CL} Press Enter to continue..." >&2
|
||||
read -r </dev/tty
|
||||
read -r
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1287,7 +1217,7 @@ prompt_confirm() {
|
||||
# Interactive prompt with timeout
|
||||
echo -en "${YW}${message} ${hint} (auto-${default} in ${timeout}s): ${CL}"
|
||||
|
||||
if read -t "$timeout" -r response </dev/tty; then
|
||||
if read -t "$timeout" -r response; then
|
||||
# User provided input
|
||||
response="${response,,}" # lowercase
|
||||
case "$response" in
|
||||
@@ -1380,7 +1310,7 @@ prompt_input() {
|
||||
# Interactive prompt with timeout
|
||||
echo -en "${YW}${message}${hint} (auto-default in ${timeout}s): ${CL}" >&2
|
||||
|
||||
if read -t "$timeout" -r response </dev/tty; then
|
||||
if read -t "$timeout" -r response; then
|
||||
# User provided input (or pressed Enter for empty)
|
||||
if [[ -n "$response" ]]; then
|
||||
echo "$response"
|
||||
@@ -1482,7 +1412,7 @@ prompt_input_required() {
|
||||
|
||||
echo -en "${YW}${message} (required, timeout ${timeout}s): ${CL}" >&2
|
||||
|
||||
if read -t "$timeout" -r response </dev/tty; then
|
||||
if read -t "$timeout" -r response; then
|
||||
if [[ -z "$response" ]]; then
|
||||
echo -e "${YW}This field is required. Please enter a value. (attempt ${attempts}/3)${CL}" >&2
|
||||
fi
|
||||
@@ -1577,7 +1507,7 @@ prompt_select() {
|
||||
echo -en "${YW}Select [1-${num_options}] (auto-select ${default} in ${timeout}s): ${CL}" >&2
|
||||
|
||||
local response
|
||||
if read -t "$timeout" -r response </dev/tty; then
|
||||
if read -t "$timeout" -r response; then
|
||||
if [[ -z "$response" ]]; then
|
||||
# Empty response, use default
|
||||
echo "${options[$((default - 1))]}"
|
||||
@@ -1660,7 +1590,7 @@ prompt_password() {
|
||||
# Interactive prompt with timeout (silent input)
|
||||
echo -en "${YW}${message}${hint} (timeout ${timeout}s): ${CL}" >&2
|
||||
|
||||
if read -t "$timeout" -rs response </dev/tty; then
|
||||
if read -t "$timeout" -rs response; then
|
||||
echo "" >&2 # Newline after hidden input
|
||||
if [[ -n "$response" ]]; then
|
||||
# Validate minimum length
|
||||
|
||||
@@ -499,7 +499,7 @@ error_handler() {
|
||||
|
||||
local response=""
|
||||
local read_rc
|
||||
read -t 60 -r response </dev/tty
|
||||
read -t 60 -r response
|
||||
read_rc=$?
|
||||
if [[ $read_rc -eq 0 ]]; then
|
||||
if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then
|
||||
@@ -543,7 +543,6 @@ error_handler() {
|
||||
# read itself failed (e.g. broken/closed stdin, I/O error) rather than
|
||||
# timing out - don't guess and destroy the container on a read we
|
||||
# couldn't actually capture; keep it since that's the reversible choice.
|
||||
while read -r -t 0.1 -n 1 _ </dev/tty 2>/dev/null; do :; done
|
||||
echo ""
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "Could not read your response (stdin error) - keeping container ${CTID} for safety."
|
||||
|
||||
+3
-24
@@ -37,29 +37,8 @@ fi
|
||||
# (the host is the single telemetry reporter).
|
||||
export TELEMETRY_CONTEXT="container"
|
||||
|
||||
# A freshly booted container may not have DNS up yet. `source <(curl ...)` hides
|
||||
# curl's exit code, so a failed download would silently source an empty stream.
|
||||
_bootstrap_die() {
|
||||
if declare -f msg_error >/dev/null 2>&1; then
|
||||
msg_error "$1"
|
||||
else
|
||||
echo "FATAL: $1" >&2
|
||||
fi
|
||||
exit 115
|
||||
}
|
||||
|
||||
_bootstrap_source() {
|
||||
local url="$1" probe="$2" content
|
||||
content=$(curl -fsSL --connect-timeout 10 --retry 5 --retry-connrefused --retry-delay 2 "$url") ||
|
||||
_bootstrap_die "Failed to download ${url##*/}"
|
||||
source /dev/stdin <<<"$content"
|
||||
declare -f "$probe" >/dev/null 2>&1 ||
|
||||
_bootstrap_die "${url##*/} loaded but incomplete (missing ${probe})"
|
||||
}
|
||||
|
||||
_FUNC_BASE="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc"
|
||||
_bootstrap_source "$_FUNC_BASE/core.func" load_functions
|
||||
_bootstrap_source "$_FUNC_BASE/error_handler.func" catch_errors
|
||||
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/error_handler.func)
|
||||
load_functions
|
||||
catch_errors
|
||||
|
||||
@@ -201,7 +180,7 @@ network_check() {
|
||||
|
||||
# If both IPv4 and IPv6 checks fail, prompt the user
|
||||
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt </dev/tty
|
||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||
else
|
||||
|
||||
+110
-164
@@ -1292,17 +1292,14 @@ create_temp_dir() {
|
||||
# - Copies each given file/directory into a persistent store at
|
||||
# /opt/<NSAPP>.backup, mirroring its absolute path inside the store, and
|
||||
# records it in a manifest so restore_backup needs no arguments.
|
||||
# - Idempotent per path: a path already recorded in the manifest (from this
|
||||
# run or a previous failed one) is left untouched, keeping the
|
||||
# last-known-good copy instead of overwriting it with now-partially-updated
|
||||
# data on retry. Any requested path NOT yet in the manifest is backed up
|
||||
# now and appended - so a manifest left incomplete by an interrupted prior
|
||||
# run gets completed instead of silently missing paths on restore.
|
||||
# - Idempotent: if a store from a previous (failed) run already exists, it is
|
||||
# left untouched and no new backup is taken. This keeps the last-known-good
|
||||
# data instead of overwriting it with now-partially-updated data on retry.
|
||||
# - Missing source paths are skipped with a warning (not fatal).
|
||||
# - Aborts the update on copy failure: if any file/dir cannot be backed up,
|
||||
# the script exits before the update runs against unprotected data (the
|
||||
# paths already recorded are left in place, so a retry only redoes the one
|
||||
# that failed).
|
||||
# the half-written store is removed and the script exits, so the update
|
||||
# never runs against unprotected data (and a retry re-attempts a clean
|
||||
# backup rather than skipping it).
|
||||
#
|
||||
# restore_backup
|
||||
# - Copies every path recorded in the manifest back to its origin (replacing
|
||||
@@ -1321,17 +1318,19 @@ create_backup() {
|
||||
return 0
|
||||
}
|
||||
|
||||
if ! mkdir -p "$store" || ! touch "$manifest"; then
|
||||
msg_error "Backup failed: could not create store at ${store} - aborting update"
|
||||
exit 1
|
||||
if [[ -f "$manifest" ]]; then
|
||||
msg_ok "Existing backup found at ${store}, skipping backup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
msg_info "Backing up data"
|
||||
if ! mkdir -p "$store" || ! : >"$manifest"; then
|
||||
msg_error "Backup failed: could not create store at ${store} - aborting update"
|
||||
rm -rf "$store"
|
||||
exit 1
|
||||
fi
|
||||
for path in "$@"; do
|
||||
path="${path%/}"
|
||||
if grep -qxF "$path" "$manifest" 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
if [[ ! -e "$path" ]]; then
|
||||
msg_warn "Skipping backup of '${path}' (not found)"
|
||||
continue
|
||||
@@ -1339,6 +1338,7 @@ create_backup() {
|
||||
dest="${store}/files${path}"
|
||||
if ! mkdir -p "$(dirname "$dest")" || ! cp -a "$path" "$dest"; then
|
||||
msg_error "Backup of '${path}' failed - aborting update"
|
||||
rm -rf "$store"
|
||||
exit 1
|
||||
fi
|
||||
echo "$path" >>"$manifest"
|
||||
@@ -1466,7 +1466,7 @@ prompt_for_github_token() {
|
||||
fi
|
||||
|
||||
local reply
|
||||
read -rp "${TAB}Would you like to enter a GitHub Personal Access Token (PAT)? [y/N]: " reply </dev/tty
|
||||
read -rp "${TAB}Would you like to enter a GitHub Personal Access Token (PAT)? [y/N]: " reply
|
||||
reply="${reply:-n}"
|
||||
|
||||
if [[ ! "${reply,,}" =~ ^(y|yes)$ ]]; then
|
||||
@@ -1475,7 +1475,7 @@ prompt_for_github_token() {
|
||||
|
||||
local token
|
||||
while true; do
|
||||
read -rp "${TAB}Enter your GitHub PAT: " token </dev/tty
|
||||
read -rp "${TAB}Enter your GitHub PAT: " token
|
||||
# Trim leading/trailing whitespace
|
||||
token="$(echo "$token" | xargs)"
|
||||
if [[ -z "$token" ]]; then
|
||||
@@ -2040,9 +2040,8 @@ cleanup_orphaned_sources() {
|
||||
local basename_file
|
||||
basename_file=$(basename "$sources_file")
|
||||
|
||||
# NEVER remove the distro's own base sources file (debian.sources,
|
||||
# ubuntu.sources, ...)
|
||||
if [[ "$basename_file" == "$(get_os_info id).sources" ]]; then
|
||||
# NEVER remove debian.sources - this is the standard Debian repository
|
||||
if [[ "$basename_file" == "debian.sources" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
@@ -2114,7 +2113,7 @@ ensure_apt_working() {
|
||||
# Step 4: More aggressive - remove all third-party sources
|
||||
msg_warn "APT update still failing, removing third-party sources"
|
||||
find /etc/apt/sources.list.d/ -type f \( -name "*.sources" -o -name "*.list" \) \
|
||||
! -name "$(get_os_info id).sources" -delete 2>/dev/null || true
|
||||
! -name "debian.sources" -delete 2>/dev/null || true
|
||||
|
||||
# Final attempt
|
||||
if ! $STD apt update; then
|
||||
@@ -2737,8 +2736,7 @@ get_latest_gl_tag() {
|
||||
local repo_encoded
|
||||
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
|
||||
|
||||
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
|
||||
local api_base="${gitlab_url}/api/v4/projects/${repo_encoded}/repository/tags"
|
||||
local api_base="https://gitlab.com/api/v4/projects/${repo_encoded}/repository/tags"
|
||||
local api_timeout="--connect-timeout 10 --max-time 60"
|
||||
|
||||
local header=()
|
||||
@@ -2820,7 +2818,6 @@ get_latest_gl_tag() {
|
||||
# Notes:
|
||||
# - Supports CLEAN_INSTALL=1 to wipe target before extracting
|
||||
# - Supports GITLAB_TOKEN for private/rate-limited projects
|
||||
# - Supports GITLAB_URL for self-hosted GitLab (default: https://gitlab.com)
|
||||
# - For repos that only publish tags, not formal GitLab Releases
|
||||
# (use fetch_and_deploy_gl_release for proper Releases with assets)
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -2864,9 +2861,8 @@ fetch_and_deploy_gl_tag() {
|
||||
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
|
||||
|
||||
# GitLab source tarball URL (no release needed, works for any tag).
|
||||
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
|
||||
local version_safe="${resolved_tag//\//-}"
|
||||
local tarball_url="${gitlab_url}/${repo}/-/archive/${resolved_tag}/${app_lc}-${version_safe}.tar.gz"
|
||||
local tarball_url="https://gitlab.com/${repo}/-/archive/${resolved_tag}/${app_lc}-${version_safe}.tar.gz"
|
||||
|
||||
local tmpdir
|
||||
tmpdir=$(mktemp -d) || return 1
|
||||
@@ -3974,7 +3970,7 @@ _gh_scan_older_releases() {
|
||||
local use_fallback="y"
|
||||
if [[ -t 0 ]]; then
|
||||
msg_warn "Release ${skip_tag} has no matching asset. Previous release ${rel_tag} has a compatible asset."
|
||||
read -rp "Use version ${rel_tag} instead? [Y/n] (auto-yes in 60s): " -t 60 use_fallback </dev/tty || use_fallback="y"
|
||||
read -rp "Use version ${rel_tag} instead? [Y/n] (auto-yes in 60s): " -t 60 use_fallback || use_fallback="y"
|
||||
use_fallback="${use_fallback:-y}"
|
||||
fi
|
||||
|
||||
@@ -4600,17 +4596,20 @@ setup_composer() {
|
||||
# - By default uses distro repository (docker.io) for stability
|
||||
# - Optionally uses official Docker repository for latest features
|
||||
# - Detects and migrates old Docker installations
|
||||
# - Optional: Installs/Updates Portainer CE
|
||||
# - Updates running containers interactively
|
||||
# - Cleans up legacy repository files
|
||||
#
|
||||
# Usage:
|
||||
# setup_docker # Uses official Docker repo (recommended)
|
||||
# USE_DOCKER_REPO=false setup_docker # Uses distro docker.io package
|
||||
# DOCKER_PORTAINER="true" setup_docker
|
||||
# DOCKER_LOG_DRIVER="json-file" setup_docker
|
||||
#
|
||||
# Variables:
|
||||
# USE_DOCKER_REPO - Set to "false" to use distro docker.io package
|
||||
# (default: true, uses official Docker repository)
|
||||
# DOCKER_PORTAINER - Install Portainer CE (optional, "true" to enable)
|
||||
# DOCKER_LOG_DRIVER - Log driver (optional, default: "journald")
|
||||
# DOCKER_SKIP_UPDATES - Skip container update check (optional, "true" to skip)
|
||||
#
|
||||
@@ -4621,62 +4620,16 @@ setup_composer() {
|
||||
# - Interactive per-container update prompt (Y/N, 60 s auto-no)
|
||||
# - Compose-managed containers: full restart via docker compose
|
||||
# - Standalone containers: image pull only, no destructive stop/rm
|
||||
# - Portainer is no longer managed here; use tools/addon/portainer.sh
|
||||
# - Portainer installation and update support
|
||||
# - Set DOCKER_NONINTERACTIVE=1 to skip interactive prompts (CI/unattended)
|
||||
# ------------------------------------------------------------------------------
|
||||
_docker_is_noninteractive() {
|
||||
[[ "${DOCKER_NONINTERACTIVE:-}" == "1" || "${DOCKER_NONINTERACTIVE:-}" == "true" || "${DOCKER_NONINTERACTIVE:-}" == "TRUE" ]] || [[ ! -t 0 ]]
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ensure_docker()
|
||||
#
|
||||
# - Docker precondition for addon scripts that ship a compose stack
|
||||
# - Reuses an existing installation, otherwise offers to install Docker
|
||||
# (Debian/Ubuntu via setup_docker, Alpine via apk)
|
||||
# - Aborts when the user declines or Compose is unavailable afterwards
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
return 0
|
||||
fi
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 237
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB:- }Install Docker now? (y/N): "
|
||||
local install_docker_prompt
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP:-this script}. Exiting."
|
||||
exit 254
|
||||
fi
|
||||
|
||||
if is_alpine; then
|
||||
msg_info "Installing Docker"
|
||||
$STD apk add --no-cache docker docker-cli-compose
|
||||
$STD rc-update add docker default
|
||||
$STD rc-service docker start
|
||||
msg_ok "Installed Docker"
|
||||
else
|
||||
setup_docker || {
|
||||
msg_error "Docker installation failed."
|
||||
exit 237
|
||||
}
|
||||
fi
|
||||
|
||||
if ! command -v docker &>/dev/null || ! docker compose version &>/dev/null; then
|
||||
msg_error "Docker or the Compose plugin is still unavailable after installation."
|
||||
exit 237
|
||||
fi
|
||||
}
|
||||
|
||||
setup_docker() {
|
||||
local docker_installed=false
|
||||
local portainer_installed=false
|
||||
local USE_DOCKER_REPO="${USE_DOCKER_REPO:-true}"
|
||||
|
||||
# Check if Docker is already installed
|
||||
@@ -4686,6 +4639,12 @@ setup_docker() {
|
||||
msg_info "Docker $DOCKER_CURRENT_VERSION detected"
|
||||
fi
|
||||
|
||||
# Check if Portainer is running
|
||||
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q '^portainer$'; then
|
||||
portainer_installed=true
|
||||
msg_info "Portainer container detected"
|
||||
fi
|
||||
|
||||
# Scenario 1: Use distro repository (opt-out via USE_DOCKER_REPO=false)
|
||||
if [[ "$USE_DOCKER_REPO" != "true" && "$USE_DOCKER_REPO" != "TRUE" && "$USE_DOCKER_REPO" != "1" ]]; then
|
||||
|
||||
@@ -4799,6 +4758,54 @@ EOF
|
||||
systemctl enable -q --now docker
|
||||
fi
|
||||
|
||||
# Portainer Management (common for both modes)
|
||||
if [[ "${DOCKER_PORTAINER:-}" == "true" ]]; then
|
||||
if [ "$portainer_installed" = true ]; then
|
||||
msg_info "Checking for Portainer updates"
|
||||
PORTAINER_CURRENT=$(docker inspect portainer --format='{{.Config.Image}}' 2>/dev/null | cut -d':' -f2)
|
||||
PORTAINER_LATEST=$(curl -fsSL https://registry.hub.docker.com/v2/repositories/portainer/portainer-ce/tags?page_size=100 | grep -oP '"name":"\K[0-9]+\.[0-9]+\.[0-9]+"' | head -1 | tr -d '"')
|
||||
|
||||
if [ "$PORTAINER_CURRENT" != "$PORTAINER_LATEST" ]; then
|
||||
if _docker_is_noninteractive; then
|
||||
msg_info "Skipping Portainer update prompt (non-interactive)"
|
||||
else
|
||||
read -r -p "${TAB3}Update Portainer $PORTAINER_CURRENT → $PORTAINER_LATEST? <y/N> " prompt
|
||||
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Updating Portainer"
|
||||
docker stop portainer
|
||||
docker rm portainer
|
||||
docker pull portainer/portainer-ce:latest
|
||||
docker run -d \
|
||||
-p 9000:9000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
msg_ok "Updated Portainer to $PORTAINER_LATEST"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
msg_ok "Portainer is up-to-date ($PORTAINER_CURRENT)"
|
||||
fi
|
||||
else
|
||||
msg_info "Installing Portainer"
|
||||
docker volume create portainer_data
|
||||
docker run -d \
|
||||
-p 9000:9000 \
|
||||
-p 9443:9443 \
|
||||
--name=portainer \
|
||||
--restart=always \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v portainer_data:/data \
|
||||
portainer/portainer-ce:latest
|
||||
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
msg_ok "Installed Portainer (http://${LOCAL_IP}:9000)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Container Update Check
|
||||
# - Skipped entirely when running unattended / non-interactive
|
||||
# - Compose-managed containers: offered via Y/N → docker compose pull + up -d
|
||||
@@ -4814,7 +4821,7 @@ EOF
|
||||
name=$(echo "$line" | awk '{print $1}')
|
||||
image=$(echo "$line" | awk '{print $2}')
|
||||
|
||||
# Portainer is managed by its own addon script, not this generic loop
|
||||
# Portainer containers are handled by the dedicated block above
|
||||
[[ "$name" == "portainer" || "$name" == "portainer_agent" ]] && continue
|
||||
|
||||
current_digest=$(docker inspect "$name" --format='{{.Image}}' 2>/dev/null | cut -d':' -f2 | cut -c1-12)
|
||||
@@ -4844,7 +4851,7 @@ EOF
|
||||
for entry in "${compose_updates[@]}"; do
|
||||
IFS='|' read -r name image compose_workdir compose_service <<<"$entry"
|
||||
reply=""
|
||||
if read -r -t 60 -p "${TAB3}Update ${name} (${image}) via Compose? <y/N> (auto-no in 60s): " reply </dev/tty; then
|
||||
if read -r -t 60 -p "${TAB3}Update ${name} (${image}) via Compose? <y/N> (auto-no in 60s): " reply; then
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
@@ -4862,7 +4869,7 @@ EOF
|
||||
for entry in "${standalone_updates[@]}"; do
|
||||
IFS='|' read -r name image <<<"$entry"
|
||||
reply=""
|
||||
if read -r -t 60 -p "${TAB3}Pull new image for ${name} (${image})? <y/N> (auto-no in 60s): " reply </dev/tty; then
|
||||
if read -r -t 60 -p "${TAB3}Pull new image for ${name} (${image})? <y/N> (auto-no in 60s): " reply; then
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
@@ -5457,7 +5464,7 @@ setup_hwaccel() {
|
||||
# Read with 60 second timeout
|
||||
local selection=""
|
||||
echo -n "Select GPU(s) to configure (1-${gpu_count}, A=all) [timeout 60s, default=all]: "
|
||||
if read -r -t 60 selection </dev/tty; then
|
||||
if read -r -t 60 selection; then
|
||||
selection="${selection^^}" # uppercase
|
||||
else
|
||||
echo ""
|
||||
@@ -5505,7 +5512,7 @@ setup_hwaccel() {
|
||||
echo ""
|
||||
msg_custom "🎮" "${GN}" "NVIDIA GPU passthrough detected"
|
||||
local nvidia_reply=""
|
||||
read -r -t 60 -p "${TAB3}⚙️ Install NVIDIA driver libraries in the container? [Y/n] (auto-yes in 60s): " nvidia_reply </dev/tty || nvidia_reply=""
|
||||
read -r -t 60 -p "${TAB3}⚙️ Install NVIDIA driver libraries in the container? [Y/n] (auto-yes in 60s): " nvidia_reply || nvidia_reply=""
|
||||
case "${nvidia_reply,,}" in
|
||||
n | no) install_nvidia_drivers="no" ;;
|
||||
*) install_nvidia_drivers="yes" ;;
|
||||
@@ -6940,60 +6947,6 @@ setup_mariadb_db() {
|
||||
export MARIADB_DB_PASS
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Creates a MySQL database and user (for apps that require MySQL, not MariaDB).
|
||||
#
|
||||
# Description:
|
||||
# - Creates database, user and grants using the mysql root socket login
|
||||
# - The user is created with host '%' because MySQL treats 'localhost'
|
||||
# (socket) and '127.0.0.1' (TCP) as distinct hosts; apps connecting over
|
||||
# TCP to 127.0.0.1 would not match a 'localhost' account. mysql-server
|
||||
# binds to 127.0.0.1 by default, so '%' stays local-only.
|
||||
#
|
||||
# Variables:
|
||||
# MYSQL_DB_NAME - Database name (required)
|
||||
# MYSQL_DB_USER - Database user (required)
|
||||
# MYSQL_DB_PASS - Password (optional, generated if unset)
|
||||
#
|
||||
# Exports:
|
||||
# MYSQL_DB_NAME, MYSQL_DB_USER, MYSQL_DB_PASS
|
||||
#
|
||||
# Example:
|
||||
# MYSQL_DB_NAME="fleet" MYSQL_DB_USER="fleet" setup_mysql_db
|
||||
# ------------------------------------------------------------------------------
|
||||
setup_mysql_db() {
|
||||
if [[ -z "${MYSQL_DB_NAME:-}" || -z "${MYSQL_DB_USER:-}" ]]; then
|
||||
msg_error "MYSQL_DB_NAME and MYSQL_DB_USER must be set before calling setup_mysql_db"
|
||||
return 65
|
||||
fi
|
||||
|
||||
if [[ -z "${MYSQL_DB_PASS:-}" ]]; then
|
||||
MYSQL_DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
|
||||
fi
|
||||
|
||||
msg_info "Setting up MySQL Database"
|
||||
|
||||
$STD mysql -u root -e "CREATE DATABASE \`${MYSQL_DB_NAME//\`/\`\`}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
$STD mysql -u root -e "CREATE USER '${MYSQL_DB_USER//\'/\'\'}'@'%' IDENTIFIED BY '${MYSQL_DB_PASS//\'/\'\'}';"
|
||||
$STD mysql -u root -e "GRANT ALL ON \`${MYSQL_DB_NAME//\`/\`\`}\`.* TO '${MYSQL_DB_USER//\'/\'\'}'@'%';"
|
||||
$STD mysql -u root -e "FLUSH PRIVILEGES;"
|
||||
|
||||
local app_name="${APPLICATION,,}"
|
||||
local CREDS_FILE="${MYSQL_DB_CREDS_FILE:-${HOME}/${app_name}.creds}"
|
||||
{
|
||||
echo "MySQL Credentials"
|
||||
echo "Database: $MYSQL_DB_NAME"
|
||||
echo "User: $MYSQL_DB_USER"
|
||||
echo "Password: $MYSQL_DB_PASS"
|
||||
} >>"$CREDS_FILE"
|
||||
|
||||
msg_ok "Set up MySQL Database"
|
||||
|
||||
export MYSQL_DB_NAME
|
||||
export MYSQL_DB_USER
|
||||
export MYSQL_DB_PASS
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Installs or updates MeiliSearch search engine.
|
||||
#
|
||||
@@ -7732,16 +7685,6 @@ setup_nodejs() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# npm >=11 skips native-module install/rebuild scripts (better-sqlite3, bcrypt,
|
||||
# argon2, ...) unless each package is explicitly allowlisted, silently leaving
|
||||
# native deps unbuilt. Bypass the policy globally instead of allowlisting
|
||||
# per script.
|
||||
local npm_major
|
||||
npm_major=$(npm -v 2>/dev/null | cut -d. -f1)
|
||||
if [[ "${npm_major:-0}" -ge 11 ]]; then
|
||||
$STD npm config set dangerously-allow-all-scripts true --location=global 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Set a safe default heap limit for Node.js builds if not explicitly provided.
|
||||
# Priority:
|
||||
# 1) NODE_OPTIONS (caller/user override)
|
||||
@@ -8252,17 +8195,22 @@ EOF
|
||||
# ------------------------------------------------------------------------------
|
||||
get_php_fpm_socket() {
|
||||
local sock
|
||||
|
||||
if [[ -n "${PHP_VERSION:-}" && -S "/run/php/php${PHP_VERSION}-fpm.sock" ]]; then
|
||||
echo "/run/php/php${PHP_VERSION}-fpm.sock"
|
||||
return 0
|
||||
fi
|
||||
|
||||
sock=$(find /run/php -maxdepth 1 -name "php*-fpm.sock" -type s 2>/dev/null | sort -V | tail -1)
|
||||
|
||||
if [[ -z "$sock" ]]; then
|
||||
msg_error "No active PHP-FPM socket found under /run/php"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$sock"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Enables an nginx site, validates the configuration and reloads the service.
|
||||
#
|
||||
@@ -8284,20 +8232,25 @@ get_php_fpm_socket() {
|
||||
# ------------------------------------------------------------------------------
|
||||
nginx_enable_site() {
|
||||
local site="${1:-}"
|
||||
|
||||
if [[ -z "$site" ]]; then
|
||||
msg_error "nginx_enable_site: no site name given"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "/etc/nginx/sites-available/${site}" ]]; then
|
||||
msg_error "nginx site config not found: /etc/nginx/sites-available/${site}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
|
||||
ln -sf "/etc/nginx/sites-available/${site}" "/etc/nginx/sites-enabled/${site}"
|
||||
|
||||
if ! $STD nginx -t; then
|
||||
msg_error "nginx configuration test failed for site '${site}'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
$STD systemctl enable -q nginx
|
||||
safe_service_restart nginx
|
||||
}
|
||||
@@ -9494,12 +9447,11 @@ get_latest_gitlab_release() {
|
||||
local temp_file
|
||||
temp_file=$(mktemp)
|
||||
|
||||
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
|
||||
local http_code
|
||||
http_code=$(curl --connect-timeout 10 --max-time 30 -sSL \
|
||||
-w "%{http_code}" -o "$temp_file" \
|
||||
"${header[@]}" \
|
||||
"${gitlab_url}/api/v4/projects/$repo_encoded/releases?per_page=1&order_by=released_at&sort=desc" 2>/dev/null) || true
|
||||
"https://gitlab.com/api/v4/projects/$repo_encoded/releases?per_page=1&order_by=released_at&sort=desc" 2>/dev/null) || true
|
||||
|
||||
if [[ "$http_code" != "200" ]]; then
|
||||
rm -f "$temp_file"
|
||||
@@ -9541,7 +9493,6 @@ get_latest_gitlab_release() {
|
||||
# Notes:
|
||||
# - Requires `jq` (auto-installed if missing)
|
||||
# - Supports GITLAB_TOKEN env var for private/rate-limited repos
|
||||
# - Supports GITLAB_URL for self-hosted GitLab (default: https://gitlab.com)
|
||||
# - Does not modify anything, only checks version state
|
||||
# ------------------------------------------------------------------------------
|
||||
check_for_gl_release() {
|
||||
@@ -9553,15 +9504,11 @@ check_for_gl_release() {
|
||||
local app_lc="${app,,}"
|
||||
local current_file="$HOME/.${app_lc}"
|
||||
|
||||
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
|
||||
local gitlab_hostname="${gitlab_url#*://}"
|
||||
gitlab_hostname="${gitlab_hostname%%/*}"
|
||||
|
||||
msg_info "Checking for update: ${app}"
|
||||
|
||||
# DNS check
|
||||
if ! getent hosts "$gitlab_hostname" >/dev/null 2>&1; then
|
||||
msg_error "Network error: cannot resolve $gitlab_hostname"
|
||||
if ! getent hosts gitlab.com >/dev/null 2>&1; then
|
||||
msg_error "Network error: cannot resolve gitlab.com"
|
||||
return 6
|
||||
fi
|
||||
|
||||
@@ -9584,7 +9531,7 @@ check_for_gl_release() {
|
||||
local pinned_encoded="${pinned_version_in//\//%2F}"
|
||||
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \
|
||||
"${header[@]}" \
|
||||
"${gitlab_url}/api/v4/projects/$repo_encoded/releases/$pinned_encoded" 2>/dev/null) || true
|
||||
"https://gitlab.com/api/v4/projects/$repo_encoded/releases/$pinned_encoded" 2>/dev/null) || true
|
||||
if [[ "$http_code" == "200" ]] && [[ -s "$gl_check_json" ]]; then
|
||||
releases_json="[$(<"$gl_check_json")]"
|
||||
fi
|
||||
@@ -9595,7 +9542,7 @@ check_for_gl_release() {
|
||||
if [[ -z "$releases_json" ]]; then
|
||||
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \
|
||||
"${header[@]}" \
|
||||
"${gitlab_url}/api/v4/projects/$repo_encoded/releases?per_page=100&order_by=released_at&sort=desc" 2>/dev/null) || true
|
||||
"https://gitlab.com/api/v4/projects/$repo_encoded/releases?per_page=100&order_by=released_at&sort=desc" 2>/dev/null) || true
|
||||
|
||||
if [[ "$http_code" == "200" ]] && [[ -s "$gl_check_json" ]]; then
|
||||
releases_json=$(<"$gl_check_json")
|
||||
@@ -9619,7 +9566,7 @@ check_for_gl_release() {
|
||||
return 22
|
||||
elif [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
||||
msg_error "GitLab API connection failed (no response)."
|
||||
msg_error "Check your network/DNS: curl -sSL ${gitlab_url}/api/v4/version"
|
||||
msg_error "Check your network/DNS: curl -sSL https://gitlab.com/api/v4/version"
|
||||
rm -f "$gl_check_json"
|
||||
return 7
|
||||
else
|
||||
@@ -9813,7 +9760,7 @@ _gl_scan_older_releases() {
|
||||
local use_fallback="y"
|
||||
if [[ -t 0 ]]; then
|
||||
msg_warn "Release ${skip_tag} has no matching asset. Previous release ${rel_tag} has a compatible asset."
|
||||
read -rp "Use version ${rel_tag} instead? [Y/n] (auto-yes in 60s): " -t 60 use_fallback </dev/tty || use_fallback="y"
|
||||
read -rp "Use version ${rel_tag} instead? [Y/n] (auto-yes in 60s): " -t 60 use_fallback || use_fallback="y"
|
||||
use_fallback="${use_fallback:-y}"
|
||||
fi
|
||||
|
||||
@@ -9864,8 +9811,7 @@ fetch_and_deploy_gl_release() {
|
||||
local repo_encoded
|
||||
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
|
||||
|
||||
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
|
||||
local api_base="${gitlab_url}/api/v4/projects/$repo_encoded/releases"
|
||||
local api_base="https://gitlab.com/api/v4/projects/$repo_encoded/releases"
|
||||
local api_url
|
||||
if [[ "$version" != "latest" ]]; then
|
||||
api_url="$api_base/$version"
|
||||
@@ -9914,7 +9860,7 @@ fetch_and_deploy_gl_release() {
|
||||
msg_error " export GITLAB_TOKEN=\"glpat-your_token_here\""
|
||||
elif [[ "$http_code" == "000" || -z "$http_code" ]]; then
|
||||
msg_error "GitLab API connection failed (no response)."
|
||||
msg_error "Check your network/DNS: curl -sSL ${gitlab_url}/api/v4/version"
|
||||
msg_error "Check your network/DNS: curl -sSL https://gitlab.com/api/v4/version"
|
||||
else
|
||||
msg_error "Failed to fetch release metadata (HTTP $http_code)"
|
||||
fi
|
||||
@@ -9969,7 +9915,7 @@ fetch_and_deploy_gl_release() {
|
||||
|
||||
### Tarball Mode ###
|
||||
if [[ "$mode" == "tarball" || "$mode" == "source" ]]; then
|
||||
local direct_tarball_url="${gitlab_url}/$repo/-/archive/$tag_name/${app_lc}-${version_safe}.tar.gz"
|
||||
local direct_tarball_url="https://gitlab.com/$repo/-/archive/$tag_name/${app_lc}-${version_safe}.tar.gz"
|
||||
filename="${app_lc}-${version_safe}.tar.gz"
|
||||
|
||||
_download_source_tarball "$direct_tarball_url" "$tmpdir/$filename" "${header[@]}" || {
|
||||
@@ -10017,7 +9963,7 @@ fetch_and_deploy_gl_release() {
|
||||
|
||||
if [[ -z "$url_match" ]]; then
|
||||
local fallback_json
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "binary" "$asset_pattern" "$tag_name"); then
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "binary" "$asset_pattern" "$tag_name"); then
|
||||
json="$fallback_json"
|
||||
tag_name=$(echo "$json" | jq -r '.tag_name // empty')
|
||||
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
|
||||
@@ -10089,7 +10035,7 @@ fetch_and_deploy_gl_release() {
|
||||
|
||||
if [[ -z "$asset_url" ]]; then
|
||||
local fallback_json
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "prebuild" "$pattern" "$tag_name"); then
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "prebuild" "$pattern" "$tag_name"); then
|
||||
json="$fallback_json"
|
||||
tag_name=$(echo "$json" | jq -r '.tag_name // empty')
|
||||
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
|
||||
@@ -10142,7 +10088,7 @@ fetch_and_deploy_gl_release() {
|
||||
|
||||
if [[ -z "$asset_url" ]]; then
|
||||
local fallback_json
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "singlefile" "$pattern" "$tag_name"); then
|
||||
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "singlefile" "$pattern" "$tag_name"); then
|
||||
json="$fallback_json"
|
||||
tag_name=$(echo "$json" | jq -r '.tag_name // empty')
|
||||
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -25,7 +20,6 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "actual-budget
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -37,6 +31,14 @@ INSTALL_PATH="/opt/actual-budget-prometheus-exporter"
|
||||
CONFIG_PATH="/opt/actual-budget-prometheus-exporter.env"
|
||||
SERVICE_PATH="/etc/systemd/system/actual-budget-prometheus-exporter.service"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
@@ -6,45 +6,39 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://netbird.io/ | Github: https://github.com/netbirdio/netbird
|
||||
|
||||
APP="add-netbird-lxc"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ ____ _ __
|
||||
/ | / /__ / /_/ __ )(_)________/ /
|
||||
/ |/ / _ \/ __/ __ / / ___/ __ /
|
||||
/ /| / __/ /_/ /_/ / / / / /_/ /
|
||||
/_/ |_/\___/\__/_____/_/_/ \__,_/
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
EOF
|
||||
}
|
||||
header_info
|
||||
set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
while true; do
|
||||
read -r -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)? " yn
|
||||
read -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit 0 ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
echo -e "Loading container list..."
|
||||
function msg() {
|
||||
local TEXT="$1"
|
||||
echo -e "$TEXT"
|
||||
}
|
||||
|
||||
NODE=$(hostname)
|
||||
MSG_MAX_LENGTH=0
|
||||
@@ -67,51 +61,37 @@ done
|
||||
|
||||
LXC_STATUS=$(pct status "$CTID" | awk '{print $2}')
|
||||
if [[ "$LXC_STATUS" != "running" ]]; then
|
||||
msg_info "Container $CTID is not running. Starting it now..."
|
||||
msg "\e[1;33m The container $CTID is not running. Starting it now...\e[0m"
|
||||
pct start "$CTID"
|
||||
while [[ "$(pct status "$CTID" | awk '{print $2}')" != "running" ]]; do
|
||||
msg_info "Waiting for the container to start..."
|
||||
msg "\e[1;33m Waiting for the container to start...\e[0m"
|
||||
sleep 2
|
||||
done
|
||||
msg_ok "Container $CTID is now running."
|
||||
msg "\e[1;32m Container $CTID is now running.\e[0m"
|
||||
fi
|
||||
|
||||
DISTRO=$(pct exec "$CTID" -- cat /etc/os-release | grep -w "ID" | cut -d'=' -f2 | tr -d '"')
|
||||
if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then
|
||||
msg_error "This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting..."
|
||||
msg "\e[1;31m Error: This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting...\e[0m"
|
||||
exit 238
|
||||
fi
|
||||
|
||||
CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
|
||||
cat <<EOF >>"$CTID_CONFIG_PATH"
|
||||
CTID_CONFIG_PATH=/etc/pve/lxc/${CTID}.conf
|
||||
cat <<EOF >>$CTID_CONFIG_PATH
|
||||
lxc.cgroup2.devices.allow: c 10:200 rwm
|
||||
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
||||
EOF
|
||||
|
||||
msg_info "Installing NetBird"
|
||||
header_info
|
||||
msg "Installing NetBird..."
|
||||
pct exec "$CTID" -- bash -c '
|
||||
set -e
|
||||
if ! command -v curl &>/dev/null; then
|
||||
apt-get update -qq
|
||||
apt-get install -y curl >/dev/null
|
||||
fi
|
||||
apt-get install -y ca-certificates gpg &>/dev/null
|
||||
|
||||
# Reuse the shared repository helper instead of hand-rolling the sources entry
|
||||
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)
|
||||
load_functions
|
||||
|
||||
# Drop the legacy keyring from the pre-deb822 layout
|
||||
rm -f /usr/share/keyrings/netbird-archive-keyring.gpg
|
||||
|
||||
setup_deb822_repo \
|
||||
"netbird" \
|
||||
"https://pkgs.netbird.io/debian/public.key" \
|
||||
"https://pkgs.netbird.io/debian" \
|
||||
"stable" \
|
||||
"main"
|
||||
|
||||
apt install -y ca-certificates gpg &>/dev/null
|
||||
curl -fsSL "https://pkgs.netbird.io/debian/public.key" | gpg --dearmor >/usr/share/keyrings/netbird-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/netbird-archive-keyring.gpg] https://pkgs.netbird.io/debian stable main" >/etc/apt/sources.list.d/netbird.list
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y netbird-ui &>/dev/null
|
||||
if systemctl list-unit-files docker.service &>/dev/null; then
|
||||
mkdir -p /etc/systemd/system/netbird.service.d
|
||||
@@ -123,5 +103,6 @@ OVERRIDE
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
'
|
||||
msg_ok "Installed NetBird."
|
||||
echo -e "${YW}Reboot ${CTID} LXC${CL} to apply the changes, then run 'netbird up' in the LXC console"
|
||||
msg "\e[1;32m ✔ Installed NetBird.\e[0m"
|
||||
sleep 2
|
||||
msg "\e[1;31m Reboot ${CTID} LXC to apply the changes, then run netbird up in the LXC console\e[0m"
|
||||
|
||||
@@ -5,34 +5,35 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://tailscale.com/ | Github: https://github.com/tailscale/tailscale
|
||||
|
||||
APP="add-tailscale-lxc"
|
||||
APP_TYPE="addon"
|
||||
set -Eeuo pipefail
|
||||
trap 'echo -e "\n[ERROR] in line $LINENO: exit code $?"' ERR
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ _ __ __
|
||||
/_ __/___ _(_) /_____________ _/ /__
|
||||
/ / / __ `/ / / ___/ ___/ __ `/ / _ \
|
||||
/ / / /_/ / / (__ ) /__/ /_/ / / __/
|
||||
/_/ \__,_/_/_/____/\___/\__,_/_/\___/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function msg_info() { echo -e " \e[1;36m➤\e[0m $1"; }
|
||||
function msg_ok() { echo -e " \e[1;32m✔\e[0m $1"; }
|
||||
function msg_error() { echo -e " \e[1;31m✖\e[0m $1"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-tailscale-lxc" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
if ! command -v pveversion &>/dev/null; then
|
||||
msg_error "This script must be run on the Proxmox VE host (not inside an LXC container)"
|
||||
exit 232
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -rp "This will add Tailscale to an existing LXC Container ONLY. Proceed (y/n)? " yn
|
||||
@@ -43,6 +44,7 @@ while true; do
|
||||
esac
|
||||
done
|
||||
|
||||
header_info
|
||||
msg_info "Loading container list..."
|
||||
|
||||
NODE=$(hostname)
|
||||
@@ -71,9 +73,10 @@ CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
|
||||
grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$CTID_CONFIG_PATH" || echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >>"$CTID_CONFIG_PATH"
|
||||
grep -q "lxc.mount.entry: /dev/net/tun" "$CTID_CONFIG_PATH" || echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >>"$CTID_CONFIG_PATH"
|
||||
|
||||
header_info
|
||||
msg_info "Installing Tailscale in CT $CTID"
|
||||
|
||||
pct exec "$CTID" -- bash -c '
|
||||
pct exec "$CTID" -- sh -c '
|
||||
set -e
|
||||
|
||||
# Detect OS inside container
|
||||
@@ -141,21 +144,16 @@ else
|
||||
apt-get install -y curl >/dev/null
|
||||
fi
|
||||
|
||||
# Reuse the shared repository helper instead of hand-rolling the sources entry
|
||||
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)
|
||||
load_functions
|
||||
# Ensure keyrings directory exists
|
||||
mkdir -p /usr/share/keyrings
|
||||
|
||||
# Drop the legacy keyring from the pre-deb822 layout
|
||||
rm -f /usr/share/keyrings/tailscale-archive-keyring.gpg
|
||||
curl -fsSL "https://pkgs.tailscale.com/stable/${ID}/${VERSION_CODENAME}.noarmor.gpg" \
|
||||
| tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
||||
|
||||
setup_deb822_repo \
|
||||
"tailscale" \
|
||||
"https://pkgs.tailscale.com/stable/${ID}/${VERSION_CODENAME}.noarmor.gpg" \
|
||||
"https://pkgs.tailscale.com/stable/${ID}" \
|
||||
"${VERSION_CODENAME}" \
|
||||
"main"
|
||||
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/${ID} ${VERSION_CODENAME} main" \
|
||||
>/etc/apt/sources.list.d/tailscale.list
|
||||
|
||||
apt-get update -qq
|
||||
apt-get install -y tailscale >/dev/null
|
||||
|
||||
if [ -f /tmp/resolv.conf.backup ]; then
|
||||
@@ -170,4 +168,4 @@ TAGS="${TAGS:+$TAGS; }tailscale"
|
||||
pct set "$CTID" -tags "$TAGS"
|
||||
|
||||
msg_ok "Tailscale installed on CT $CTID"
|
||||
echo -e "${YW}Reboot the container${CL}, then run 'tailscale up' inside the container to activate."
|
||||
msg_info "Reboot the container, then run 'tailscale up' inside the container to activate."
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
apk -U add curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
@@ -37,6 +36,28 @@ DEFAULT_PORT=8080
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ __ ____ __ _____
|
||||
/ | ____/ /___ ___ ______ __________/ / / / /___ ____ ___ ___ / ___/__ ______ _____
|
||||
/ /| |/ __ / __ `/ / / / __ `/ ___/ __ / /_/ / __ \/ __ `__ \/ _ \ \__ \/ / / / __ \/ ___/
|
||||
/ ___ / /_/ / /_/ / /_/ / /_/ / / / /_/ / __ / /_/ / / / / / / __/ ___/ / /_/ / / / / /__
|
||||
/_/ |_\__,_/\__, /\__,_/\__,_/_/ \__,_/_/ /_/\____/_/ /_/ /_/\___/ /____/\__, /_/ /_/\___/
|
||||
/____/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ==============================================================================
|
||||
get_ip() {
|
||||
hostname -I 2>/dev/null | awk '{print $1}' || ip -4 addr show scope global 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1 || echo "127.0.0.1"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
@@ -93,12 +114,16 @@ function update() {
|
||||
fi
|
||||
msg_ok "Stopped service"
|
||||
|
||||
BACKUP_DIR="/opt/adguardhome-sync_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/adguardhome-sync.yaml.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_amd64.tar.gz"
|
||||
|
||||
restore_backup
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/adguardhome-sync.yaml.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/adguardhome-sync.yaml.bak
|
||||
msg_ok "Restored configuration"
|
||||
|
||||
msg_info "Starting service"
|
||||
if [[ "$OS" == "Alpine" ]]; then
|
||||
@@ -116,7 +141,10 @@ function update() {
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
|
||||
local ip
|
||||
ip=$(get_ip)
|
||||
|
||||
fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_amd64.tar.gz"
|
||||
|
||||
# Gather configuration from user
|
||||
echo ""
|
||||
@@ -125,7 +153,7 @@ function install() {
|
||||
echo ""
|
||||
|
||||
# Origin instance
|
||||
echo -e "${YW}── Origin (Primary) Instance ──${CL}"
|
||||
echo -e "${YW}── Origin (Primary) Instance ──${CL}"
|
||||
local origin_url origin_user origin_pass
|
||||
read -rp " Origin URL (e.g., http://192.168.1.1): " origin_url
|
||||
origin_url="${origin_url:-http://192.168.1.1}"
|
||||
@@ -139,7 +167,7 @@ function install() {
|
||||
|
||||
# Replica instance
|
||||
echo ""
|
||||
echo -e "${YW}── Replica Instance ──${CL}"
|
||||
echo -e "${YW}── Replica Instance ──${CL}"
|
||||
local replica_url replica_user replica_pass
|
||||
read -rp " Replica URL (e.g., http://192.168.1.2): " replica_url
|
||||
replica_url="${replica_url:-http://192.168.1.2}"
|
||||
@@ -265,7 +293,7 @@ UPDATEEOF
|
||||
|
||||
echo ""
|
||||
msg_ok "${APP} installed successfully"
|
||||
msg_ok "Web UI: ${BL}http://${IP}:${DEFAULT_PORT}${CL}"
|
||||
msg_ok "Web UI: ${BL}http://${ip}:${DEFAULT_PORT}${CL}"
|
||||
msg_ok "Config: ${BL}${CONFIG_PATH}${CL}"
|
||||
echo ""
|
||||
msg_warn "Edit the config file to add your AdGuardHome instances!"
|
||||
@@ -291,8 +319,7 @@ fi
|
||||
|
||||
header_info
|
||||
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
IP=$(get_ip)
|
||||
|
||||
# Check if already installed
|
||||
if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/adguardhome-sync" ]]; then
|
||||
|
||||
@@ -1,40 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
APP="all-templates"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ ____ ______ __ __
|
||||
/ _ | / / / /_ __/__ __ _ ___ / /__ _/ /____ ___
|
||||
/ __ |/ / / / / / -_) ' \/ _ \/ / _ `/ __/ -_|_-<
|
||||
/_/ |_/_/_/ /_/ \__/_/_/_/ .__/_/\_,_/\__/\__/___/
|
||||
/_/
|
||||
EOF
|
||||
}
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
set -eEuo pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local DEFAULT='Unknown failure occured.'
|
||||
local REASON="\e[97m${1:-$DEFAULT}\e[39m"
|
||||
local FLAG="\e[91m[ERROR] \e[93m$EXIT@$LINE"
|
||||
msg "$FLAG $REASON" 1>&2
|
||||
[ ! -z ${CTID-} ] && cleanup_ctid
|
||||
exit $EXIT
|
||||
}
|
||||
function warn() {
|
||||
local REASON="\e[97m$1\e[39m"
|
||||
local FLAG="\e[93m[WARNING]\e[39m"
|
||||
msg "$FLAG $REASON"
|
||||
}
|
||||
function info() {
|
||||
local REASON="$1"
|
||||
local FLAG="\e[36m[INFO]\e[39m"
|
||||
msg "$FLAG $REASON"
|
||||
}
|
||||
function msg() {
|
||||
local TEXT="$1"
|
||||
echo -e "$TEXT"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "addon"
|
||||
|
||||
# Enable error handling; destroy any partially-created container before reporting the error
|
||||
set -Eeuo pipefail
|
||||
function _cleanup_on_error() {
|
||||
local ec=$? cmd="$BASH_COMMAND"
|
||||
[[ -n "${CTID:-}" ]] && cleanup_ctid
|
||||
error_handler "$ec" "$cmd"
|
||||
}
|
||||
trap '_cleanup_on_error' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
function validate_container_id() {
|
||||
local ctid="$1"
|
||||
# Check if ID is numeric
|
||||
@@ -67,14 +79,12 @@ function cleanup_ctid() {
|
||||
fi
|
||||
}
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
# Stop Proxmox VE Monitor-All if running
|
||||
if systemctl is-active -q ping-instances.service; then
|
||||
systemctl stop ping-instances.service
|
||||
fi
|
||||
msg_info "Loading"
|
||||
header_info
|
||||
echo "Loading..."
|
||||
pveam update >/dev/null 2>&1
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templates" --yesno "This will allow for the creation of one of the many Template LXC Containers. Proceed?" 10 68
|
||||
TEMPLATE_MENU=()
|
||||
@@ -87,8 +97,8 @@ done < <(pveam available)
|
||||
TEMPLATE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Template LXCs" --radiolist "\nSelect a Template LXC to create:\n" 16 $((MSG_MAX_LENGTH + 58)) 10 "${TEMPLATE_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
|
||||
[ -z "$TEMPLATE" ] && {
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Template LXC Selected" --msgbox "It appears that no Template LXC container was selected" 10 68
|
||||
echo "Done"
|
||||
exit 0
|
||||
msg "Done"
|
||||
exit
|
||||
}
|
||||
|
||||
# Setup script environment
|
||||
@@ -98,9 +108,9 @@ PASS="$(openssl rand -base64 8)"
|
||||
# Get valid Container ID
|
||||
CTID=$(pvesh get /cluster/nextid)
|
||||
if ! validate_container_id "$CTID"; then
|
||||
msg_warn "Container ID $CTID is already in use."
|
||||
warn "Container ID $CTID is already in use."
|
||||
CTID=$(get_valid_container_id "$CTID")
|
||||
msg_info "Using next available ID: $CTID"
|
||||
info "Using next available ID: $CTID"
|
||||
fi
|
||||
|
||||
PCT_OPTIONS="
|
||||
@@ -132,10 +142,7 @@ function select_storage() {
|
||||
CONTENT='vztmpl'
|
||||
CONTENT_LABEL='Container template'
|
||||
;;
|
||||
*)
|
||||
msg_error "Invalid storage class."
|
||||
exit 112
|
||||
;;
|
||||
*) false || die "Invalid storage class." ;;
|
||||
esac
|
||||
|
||||
# Query all storage locations
|
||||
@@ -154,9 +161,8 @@ function select_storage() {
|
||||
|
||||
# Select storage location
|
||||
if [ $((${#MENU[@]} / 3)) -eq 0 ]; then
|
||||
msg_warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
|
||||
msg_error "Unable to detect valid storage location."
|
||||
if [[ "$CONTENT" == "rootdir" ]]; then exit 119; else exit 120; fi
|
||||
warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
|
||||
die "Unable to detect valid storage location."
|
||||
elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
||||
printf ${MENU[0]}
|
||||
else
|
||||
@@ -165,54 +171,43 @@ function select_storage() {
|
||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||
"Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\n\n" \
|
||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||
"${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
||||
msg_error "Menu aborted."
|
||||
exit 254
|
||||
}
|
||||
"${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
|
||||
done
|
||||
printf $STORAGE
|
||||
fi
|
||||
}
|
||||
|
||||
header_info
|
||||
# Get template storage
|
||||
TEMPLATE_STORAGE=$(select_storage template)
|
||||
msg_info "Using '$TEMPLATE_STORAGE' for template storage."
|
||||
info "Using '$TEMPLATE_STORAGE' for template storage."
|
||||
|
||||
# Get container storage
|
||||
CONTAINER_STORAGE=$(select_storage container)
|
||||
msg_info "Using '$CONTAINER_STORAGE' for container storage."
|
||||
info "Using '$CONTAINER_STORAGE' for container storage."
|
||||
|
||||
# Download template
|
||||
msg_info "Downloading LXC template (Patience)"
|
||||
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || {
|
||||
msg_error "A problem occured while downloading the LXC template."
|
||||
exit 222
|
||||
}
|
||||
msg_ok "Downloaded LXC template"
|
||||
msg "Downloading LXC template (Patience)..."
|
||||
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || die "A problem occured while downloading the LXC template."
|
||||
|
||||
# Create variable for 'pct' options
|
||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
||||
[[ " ${PCT_OPTIONS[*]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
|
||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
|
||||
|
||||
# Create LXC
|
||||
msg_info "Creating LXC container"
|
||||
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} "${PCT_OPTIONS[@]}" >/dev/null || {
|
||||
msg_error "A problem occured while trying to create container."
|
||||
exit 209
|
||||
}
|
||||
msg_ok "Created LXC container"
|
||||
msg "Creating LXC container..."
|
||||
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null ||
|
||||
die "A problem occured while trying to create container."
|
||||
|
||||
# Save password
|
||||
echo "$NAME password: ${PASS}" >>~/$NAME.creds # file is located in the Proxmox root directory
|
||||
|
||||
# Start container
|
||||
msg_info "Starting LXC Container"
|
||||
msg "Starting LXC Container..."
|
||||
pct start "$CTID"
|
||||
sleep 5
|
||||
msg_ok "Started LXC Container"
|
||||
|
||||
# Get container IP
|
||||
set +Eeuo pipefail
|
||||
set +eEuo pipefail
|
||||
max_attempts=5
|
||||
attempt=1
|
||||
IP=""
|
||||
@@ -221,29 +216,30 @@ while [[ $attempt -le $max_attempts ]]; do
|
||||
if [[ -n $IP ]]; then
|
||||
break
|
||||
else
|
||||
msg_warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
|
||||
warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
|
||||
sleep 5
|
||||
((attempt++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $IP ]]; then
|
||||
msg_warn "Maximum number of attempts reached. IP address not found."
|
||||
warn "Maximum number of attempts reached. IP address not found."
|
||||
IP="NOT FOUND"
|
||||
fi
|
||||
|
||||
set -Eeuo pipefail
|
||||
set -eEuo pipefail
|
||||
# Start Proxmox VE Monitor-All if available
|
||||
if [[ -f /etc/systemd/system/ping-instances.service ]]; then
|
||||
systemctl start ping-instances.service
|
||||
fi
|
||||
|
||||
# Success message
|
||||
header_info
|
||||
echo
|
||||
msg_ok "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
|
||||
info "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
|
||||
echo
|
||||
echo -e "${YW}Proceed to the LXC console to complete the setup.${CL}"
|
||||
info "Proceed to the LXC console to complete the setup."
|
||||
echo
|
||||
echo -e "${YW}login: root${CL}"
|
||||
echo -e "${YW}password: $PASS${CL}"
|
||||
info "login: root"
|
||||
info "password: $PASS"
|
||||
echo
|
||||
|
||||
+31
-7
@@ -6,14 +6,9 @@
|
||||
# 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
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -37,6 +32,21 @@ DEFAULT_PORT=3552
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ ____ _________ _ ________
|
||||
/ | / __ \/ ____/ | / | / / ____/
|
||||
/ /| | / /_/ / / / /| | / |/ / __/
|
||||
/ ___ |/ _, _/ /___/ ___ |/ /| / /___
|
||||
/_/ |_/_/ |_|\____/_/ |_/_/ |_/_____/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -72,11 +82,26 @@ function update() {
|
||||
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 10
|
||||
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 10
|
||||
fi
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
check_docker
|
||||
|
||||
msg_info "Creating install directory"
|
||||
mkdir -p "$INSTALL_PATH"
|
||||
@@ -153,7 +178,6 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -5,83 +5,100 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://coder.com/ | Github: https://github.com/coder/code-server
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
function header_info {
|
||||
cat <<"EOF"
|
||||
______ __ _____
|
||||
/ ____/___ ____/ /__ / ___/___ ______ _____ _____
|
||||
/ / / __ \/ __ / _ \ \__ \/ _ \/ ___/ | / / _ \/ ___/
|
||||
/ /___/ /_/ / /_/ / __/ ___/ / __/ / | |/ / __/ /
|
||||
\____/\____/\__,_/\___/ /____/\___/_/ |___/\___/_/
|
||||
|
||||
EOF
|
||||
}
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="Coder Code Server"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "coder-code-server" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
|
||||
APP="Coder Code Server"
|
||||
APP_TYPE="addon"
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
ensure_usr_local_bin_persist
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
confirm_not_pve_host
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl disable --now code-server@"$USER" &>/dev/null || true
|
||||
$STD apt remove -y code-server
|
||||
rm -f "$HOME/.coder-code-server"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local reason="Unknown failure occured."
|
||||
local msg="${1:-$reason}"
|
||||
local flag="${RD}‼ ERROR ${CL}$EXIT@$LINE"
|
||||
echo -e "$flag $msg" 1>&2
|
||||
exit "$EXIT"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
if check_for_gh_release "coder-code-server" "coder/code-server"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "coder-code-server" "coder/code-server" "binary" "latest" "/opt/coder-code-server" "code-server_*_$(arch_resolve).deb"
|
||||
systemctl restart code-server@"$USER"
|
||||
msg_ok "Updated successfully!"
|
||||
clear
|
||||
header_info
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Install on Proxmox "
|
||||
exit
|
||||
fi
|
||||
if [ -e /etc/alpine-release ]; then
|
||||
echo -e "⚠️ Can't Install on Alpine"
|
||||
exit
|
||||
fi
|
||||
while true; do
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
curl \
|
||||
git
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y curl &>/dev/null
|
||||
apt-get install -y git &>/dev/null
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
VERSION=$(curl -fsSL https://api.github.com/repos/coder/code-server/releases/latest |
|
||||
grep "tag_name" |
|
||||
awk '{print substr($2, 3, length($2)-4) }')
|
||||
|
||||
msg_info "Installing Code-Server v${VERSION}"
|
||||
config_path="${HOME}/.config/code-server/config.yaml"
|
||||
preexisting_config=false
|
||||
|
||||
if [ -f "$config_path" ]; then
|
||||
preexisting_config=true
|
||||
fi
|
||||
|
||||
fetch_and_deploy_gh_release "coder-code-server" "coder/code-server" "binary" "latest" "/opt/coder-code-server" "code-server_*_$(arch_resolve).deb"
|
||||
curl -fOL https://github.com/coder/code-server/releases/download/v"$VERSION"/code-server_"${VERSION}"_amd64.deb &>/dev/null
|
||||
dpkg -i code-server_"${VERSION}"_amd64.deb &>/dev/null
|
||||
rm -rf code-server_"${VERSION}"_amd64.deb
|
||||
mkdir -p "${HOME}/.config/code-server/"
|
||||
|
||||
if [ "$preexisting_config" = false ]; then
|
||||
@@ -95,68 +112,9 @@ EOF
|
||||
systemctl enable -q --now code-server@"$USER"
|
||||
systemctl restart code-server@"$USER"
|
||||
if ! systemctl is-active --quiet code-server@"$USER"; then
|
||||
msg_error "code-server service failed to start."
|
||||
exit 150
|
||||
error_exit "code-server service failed to start."
|
||||
fi
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating update script"
|
||||
ensure_usr_local_bin_persist
|
||||
cat <<'EOF' >/usr/local/bin/update_coder-code-server
|
||||
#!/usr/bin/env bash
|
||||
# Coder Code Server Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coder-code-server.sh)"
|
||||
EOF
|
||||
chmod +x /usr/local/bin/update_coder-code-server
|
||||
msg_ok "Created update script (/usr/local/bin/update_coder-code-server)"
|
||||
msg_ok "Installed Code-Server v${VERSION} on $hostname"
|
||||
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://${IP}:8680${CL} \n"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
if command -v code-server &>/dev/null; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 233
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -d "$HOME" && -f "$HOME/.coder-code-server" ]] || command -v code-server &>/dev/null; then
|
||||
msg_warn "${APP} is already installed."
|
||||
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
|
||||
|
||||
while true; do
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
install
|
||||
${BL}http://$IP:8680${CL} \n"
|
||||
|
||||
+57
-2
@@ -66,11 +66,66 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
check_or_install_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
@@ -117,7 +172,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
check_proxmox_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
+18
-16
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -50,13 +45,28 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
SERVICE_PATH="/etc/init.d/copyparty"
|
||||
elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
||||
OS="Debian"
|
||||
PKG_MANAGER="apt install -y"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
SERVICE_PATH="/etc/systemd/system/copyparty.service"
|
||||
else
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ ____ __
|
||||
/ ____/___ ____ __ __/ __ \____ ______/ /___ __
|
||||
/ / / __ \/ __ \/ / / / /_/ / __ `/ ___/ __/ / / /
|
||||
/ /___/ /_/ / /_/ / /_/ / ____/ /_/ / / / /_/ /_/ /
|
||||
\____/\____/ .___/\__, /_/ \__,_/_/ \__/\__, /
|
||||
/_/ /____/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ==============================================================================
|
||||
@@ -163,17 +173,9 @@ function install() {
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
$STD $PKG_MANAGER \
|
||||
python3 \
|
||||
python3-pil \
|
||||
ffmpeg \
|
||||
curl
|
||||
$STD $PKG_MANAGER python3 python3-pil ffmpeg curl
|
||||
else
|
||||
$STD $PKG_MANAGER \
|
||||
python3 \
|
||||
py3-pillow \
|
||||
ffmpeg \
|
||||
curl
|
||||
$STD $PKG_MANAGER python3 py3-pillow ffmpeg curl
|
||||
fi
|
||||
msg_ok "Dependencies installed (with thumbnail support)"
|
||||
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -25,7 +20,6 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "cronmaster" "
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -37,6 +31,29 @@ CONFIG_PATH="/opt/cronmaster/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/cronmaster.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ __ ___ __
|
||||
/ ____/________ ____ / |/ /___ ______/ /____ _____
|
||||
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
|
||||
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
|
||||
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -60,12 +77,16 @@ function update() {
|
||||
systemctl stop cronmaster.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
BACKUP_DIR="/opt/cronmaster_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/cronmaster.env.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
|
||||
|
||||
restore_backup
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/cronmaster.env.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/cronmaster.env.bak
|
||||
msg_ok "Restored configuration"
|
||||
|
||||
msg_info "Starting service"
|
||||
systemctl start cronmaster
|
||||
|
||||
+63
-35
@@ -5,61 +5,89 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.crowdsec.net/ | Github: https://github.com/crowdsecurity/crowdsec
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="CrowdSec"
|
||||
APP_TYPE="addon"
|
||||
hostname="$(hostname)"
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "crowdsec" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local reason="Unknown failure occured."
|
||||
local msg="${1:-$reason}"
|
||||
local flag="${RD}‼ ERROR ${CL}$EXIT@$LINE"
|
||||
echo -e "$flag $msg" 1>&2
|
||||
exit "$EXIT"
|
||||
}
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Install on Proxmox "
|
||||
exit
|
||||
fi
|
||||
while true; do
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
clear
|
||||
function header_info() {
|
||||
echo -e "${BL}
|
||||
_____ _ _____
|
||||
/ ____| | |/ ____|
|
||||
| | _ __ _____ ____| | (___ ___ ___
|
||||
| | | __/ _ \ \ /\ / / _ |\___ \ / _ \/ __|
|
||||
| |____| | | (_) \ V V / (_| |____) | __/ (__
|
||||
\_____|_| \___/ \_/\_/ \__ _|_____/ \___|\___|
|
||||
${CL}"
|
||||
}
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_info "Setting up ${APP} Repository"
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
curl \
|
||||
gnupg
|
||||
$STD bash -c "curl -fsSL https://install.crowdsec.net | bash"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y curl &>/dev/null
|
||||
apt-get install -y gnupg &>/dev/null
|
||||
curl -fsSL "https://install.crowdsec.net" | bash &>/dev/null
|
||||
msg_ok "Setup ${APP} Repository"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
$STD apt update
|
||||
$STD apt install -y crowdsec
|
||||
msg_ok "Installed ${APP}"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y crowdsec &>/dev/null
|
||||
msg_ok "Installed ${APP} on $hostname"
|
||||
|
||||
msg_info "Installing ${APP} Common Bouncer"
|
||||
$STD apt install -y crowdsec-firewall-bouncer-iptables
|
||||
apt-get install -y crowdsec-firewall-bouncer-iptables &>/dev/null
|
||||
msg_ok "Installed ${APP} Common Bouncer"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
|
||||
+57
-2
@@ -72,11 +72,66 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
check_or_install_docker
|
||||
|
||||
msg_info "Creating install directories"
|
||||
mkdir -p "$INSTALL_PATH" "$STACKS_PATH"
|
||||
@@ -112,7 +167,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
check_proxmox_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
+57
-2
@@ -65,11 +65,66 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
check_or_install_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
@@ -115,7 +170,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
check_proxmox_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -5,51 +5,55 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/filebrowserspace/quantum
|
||||
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_______ __ ____ ____ __
|
||||
/ ____(_) /__ / __ )_________ _ __________ _____ / __ \__ ______ _____ / /___ ______ ___
|
||||
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/ / / / / / / / __ `/ __ \/ __/ / / / __ `__ \
|
||||
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ / / /_/ / /_/ / /_/ / / / / /_/ /_/ / / / / / /
|
||||
/_/ /_/_/\___/_____/_/ \____/|__/|__/____/\___/_/ \___\_\__,_/\__,_/_/ /_/\__/\__,_/_/ /_/ /_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="FileBrowser Quantum"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/usr/local/bin/filebrowser"
|
||||
CONFIG_PATH="/usr/local/community-scripts/fq-config.yaml"
|
||||
DEFAULT_PORT=8080
|
||||
SRC_DIR="/"
|
||||
TMP_BIN="/tmp/filebrowser.$$"
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser-quantum" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
# Get primary IP
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
|
||||
# Proxmox Host Warning
|
||||
if [[ -d "/etc/pve" ]]; then
|
||||
msg_warn "Running this addon directly on the Proxmox host is not recommended!"
|
||||
msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
|
||||
msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
|
||||
msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
|
||||
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}"
|
||||
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}"
|
||||
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}"
|
||||
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}"
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
|
||||
echo -n "Continue anyway on the Proxmox host? (y/N): "
|
||||
read -r host_confirm
|
||||
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Aborted."
|
||||
echo -e "${YW}Aborted.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -62,12 +66,18 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt install -y"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
else
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}$1...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Detect legacy FileBrowser installation
|
||||
LEGACY_DB="/usr/local/community-scripts/filebrowser.db"
|
||||
LEGACY_BIN="/usr/local/bin/filebrowser"
|
||||
@@ -75,82 +85,80 @@ LEGACY_SERVICE_DEB="/etc/systemd/system/filebrowser.service"
|
||||
LEGACY_SERVICE_ALP="/etc/init.d/filebrowser"
|
||||
|
||||
if [[ -f "$LEGACY_DB" || -f "$LEGACY_BIN" && ! -f "$CONFIG_PATH" ]]; then
|
||||
msg_warn "Detected legacy FileBrowser installation."
|
||||
echo -n "${TAB}Uninstall legacy FileBrowser and continue with Quantum install? (y/n): "
|
||||
echo -e "${YW}⚠️ Detected legacy FileBrowser installation.${CL}"
|
||||
echo -n "Uninstall legacy FileBrowser and continue with Quantum install? (y/n): "
|
||||
read -r remove_legacy
|
||||
if [[ "${remove_legacy,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling legacy FileBrowser"
|
||||
if [[ -f "$LEGACY_SERVICE_DEB" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
rm -f "$LEGACY_SERVICE_DEB"
|
||||
elif [[ -f "$LEGACY_SERVICE_ALP" ]]; then
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rm -f "$LEGACY_SERVICE_ALP"
|
||||
fi
|
||||
rm -f "$LEGACY_BIN" "$LEGACY_DB"
|
||||
msg_ok "Legacy FileBrowser removed"
|
||||
else
|
||||
msg_error "Installation aborted by user."
|
||||
echo -e "${YW}❌ Installation aborted by user.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Existing installation
|
||||
if [[ -f "$INSTALL_PATH" ]]; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
echo -n "Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$CONFIG_PATH" "$HOME/.filebrowser-quantum"
|
||||
rm -f "$INSTALL_PATH" "$CONFIG_PATH"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
echo -n "Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
if check_for_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser"; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $STD $PKG_MANAGER curl; fi
|
||||
fetch_and_deploy_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser" "singlefile" "latest" "/usr/local/bin" "linux-$(arch_resolve)-filebrowser"
|
||||
mv -f /usr/local/bin/filebrowser-quantum "$INSTALL_PATH"
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN"
|
||||
chmod +x "$TMP_BIN"
|
||||
mv -f "$TMP_BIN" /usr/local/bin/filebrowser
|
||||
msg_ok "Updated ${APP}"
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
msg_warn "Update skipped. Exiting."
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
msg_warn "${APP} is not installed."
|
||||
echo -n "${TAB}Enter port number (Default: ${DEFAULT_PORT}): "
|
||||
echo -e "${YW}⚠️ ${APP} is not installed.${CL}"
|
||||
echo -n "Enter port number (Default: ${DEFAULT_PORT}): "
|
||||
read -r PORT
|
||||
PORT=${PORT:-$DEFAULT_PORT}
|
||||
|
||||
echo -n "${TAB}Install ${APP}? (y/n): "
|
||||
echo -n "Install ${APP}? (y/n): "
|
||||
read -r install_prompt
|
||||
if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$STD $PKG_MANAGER \
|
||||
curl \
|
||||
ffmpeg
|
||||
fetch_and_deploy_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser" "singlefile" "latest" "/usr/local/bin" "linux-$(arch_resolve)-filebrowser"
|
||||
mv -f /usr/local/bin/filebrowser-quantum "$INSTALL_PATH"
|
||||
$PKG_MANAGER curl ffmpeg &>/dev/null
|
||||
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN"
|
||||
chmod +x "$TMP_BIN"
|
||||
mv -f "$TMP_BIN" /usr/local/bin/filebrowser
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Preparing configuration directory"
|
||||
@@ -159,7 +167,7 @@ chown root:root /usr/local/community-scripts
|
||||
chmod 755 /usr/local/community-scripts
|
||||
msg_ok "Directory prepared"
|
||||
|
||||
echo -n "${TAB}Use No Authentication? (y/N): "
|
||||
echo -n "Use No Authentication? (y/N): "
|
||||
read -r noauth_prompt
|
||||
|
||||
# === YAML CONFIG GENERATION ===
|
||||
@@ -243,9 +251,9 @@ depend() {
|
||||
}
|
||||
EOF
|
||||
chmod +x "$SERVICE_PATH"
|
||||
$STD rc-update add filebrowser default
|
||||
$STD rc-service filebrowser start
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
fi
|
||||
|
||||
msg_ok "Service created successfully"
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
|
||||
+75
-60
@@ -5,50 +5,53 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://filebrowser.org/ | Github: https://github.com/filebrowser/filebrowser
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_______ __ ____
|
||||
/ ____(_) /__ / __ )_________ _ __________ _____
|
||||
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/
|
||||
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ /
|
||||
/_/ /_/_/\___/_____/_/ \____/|__/|__/____/\___/_/
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="FileBrowser"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/usr/local/bin/filebrowser"
|
||||
DB_PATH="/usr/local/community-scripts/filebrowser.db"
|
||||
DEFAULT_PORT=8080
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
# Get first non-loopback IP & Detect primary network interface dynamically
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
|
||||
# Proxmox Host Warning
|
||||
if [[ -d "/etc/pve" ]]; then
|
||||
msg_warn "Running this addon directly on the Proxmox host is not recommended!"
|
||||
msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
|
||||
msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
|
||||
msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
|
||||
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}"
|
||||
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}"
|
||||
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}"
|
||||
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}"
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
|
||||
echo -n "Continue anyway on the Proxmox host? (y/N): "
|
||||
read -r host_confirm
|
||||
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Aborted."
|
||||
echo -e "${YW}Aborted.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -61,59 +64,71 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt install -y"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
else
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -e "${INFO} ${YW}${msg}...${CL}"
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
if [ -f "$INSTALL_PATH" ]; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH" "$HOME/.filebrowser"
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to update ${APP}? (y/N): " update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
if check_for_gh_release "filebrowser" "filebrowser/filebrowser"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "filebrowser" "filebrowser/filebrowser" "prebuild" "latest" "/opt/filebrowser-dist" "linux-$(arch_resolve)-filebrowser.tar.gz"
|
||||
install -m 755 /opt/filebrowser-dist/filebrowser "$INSTALL_PATH"
|
||||
rm -rf /opt/filebrowser-dist
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Updated ${APP}"
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
msg_warn "Update skipped. Exiting."
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
msg_warn "${APP} is not installed."
|
||||
echo -e "${YW}⚠️ ${APP} is not installed.${CL}"
|
||||
read -r -p "Enter port number (Default: ${DEFAULT_PORT}): " PORT
|
||||
PORT=${PORT:-$DEFAULT_PORT}
|
||||
|
||||
read -r -p "Would you like to install ${APP}? (y/n): " install_prompt
|
||||
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$STD $PKG_MANAGER \
|
||||
tar \
|
||||
curl
|
||||
fetch_and_deploy_gh_release "filebrowser" "filebrowser/filebrowser" "prebuild" "latest" "/opt/filebrowser-dist" "linux-$(arch_resolve)-filebrowser.tar.gz"
|
||||
install -m 755 /opt/filebrowser-dist/filebrowser "$INSTALL_PATH"
|
||||
rm -rf /opt/filebrowser-dist
|
||||
$PKG_MANAGER wget tar curl &>/dev/null
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating FileBrowser directory"
|
||||
@@ -129,19 +144,19 @@ if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Configuring No Authentication"
|
||||
cd /usr/local/community-scripts
|
||||
$STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set --auth.method=noauth --database "$DB_PATH"
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set --auth.method=noauth --database "$DB_PATH" &>/dev/null
|
||||
if ! filebrowser users update 1 --perm.admin --database "$DB_PATH" &>/dev/null; then
|
||||
$STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
|
||||
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
fi
|
||||
msg_ok "No Authentication configured"
|
||||
else
|
||||
msg_info "Setting up default authentication"
|
||||
cd /usr/local/community-scripts
|
||||
$STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
msg_ok "Default authentication configured (admin:community-scripts.org)"
|
||||
fi
|
||||
|
||||
@@ -179,13 +194,13 @@ depend() {
|
||||
}
|
||||
EOF
|
||||
chmod +x "$SERVICE_PATH"
|
||||
$STD rc-update add filebrowser default
|
||||
$STD rc-service filebrowser start
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
fi
|
||||
msg_ok "Service created successfully"
|
||||
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
else
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
+51
-42
@@ -5,47 +5,55 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://nicolargo.github.io/glances/ | Github: https://github.com/nicolargo/glances
|
||||
|
||||
APP="Glances"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
________
|
||||
/ ____/ /___ _____ ________ _____
|
||||
/ / __/ / __ `/ __ \/ ___/ _ \/ ___/
|
||||
/ /_/ / / /_/ / / / / /__/ __(__ )
|
||||
\____/_/\__,_/_/ /_/\___/\___/____/
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
EOF
|
||||
}
|
||||
|
||||
APP="Glances"
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}$1...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "glances" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
get_lxc_ip() {
|
||||
if command -v hostname >/dev/null 2>&1 && hostname -I 2>/dev/null; then
|
||||
hostname -I | awk '{print $1}'
|
||||
elif command -v ip >/dev/null 2>&1; then
|
||||
ip -4 addr show scope global | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1
|
||||
else
|
||||
echo "127.0.0.1"
|
||||
fi
|
||||
}
|
||||
IP=$(get_lxc_ip)
|
||||
|
||||
install_glances_debian() {
|
||||
msg_info "Installing dependencies"
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
gcc \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
curl
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y gcc lm-sensors wireless-tools curl >/dev/null 2>&1
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
msg_info "Setting up Python + uv"
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
setup_uv PYTHON_VERSION="3.12"
|
||||
msg_ok "Setup Python + uv"
|
||||
|
||||
@@ -53,10 +61,10 @@ install_glances_debian() {
|
||||
cd /opt
|
||||
mkdir -p glances
|
||||
cd glances
|
||||
$STD uv venv --clear
|
||||
uv venv --clear
|
||||
source .venv/bin/activate >/dev/null 2>&1
|
||||
$STD uv pip install --upgrade pip wheel setuptools
|
||||
$STD uv pip install "glances[web]"
|
||||
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1
|
||||
uv pip install "glances[web]" >/dev/null 2>&1
|
||||
deactivate
|
||||
msg_ok "Installed $APP"
|
||||
|
||||
@@ -78,7 +86,7 @@ EOF
|
||||
systemctl enable -q --now glances
|
||||
msg_ok "Created systemd service"
|
||||
|
||||
msg_ok "$APP is now running at: http://${IP}:61208"
|
||||
echo -e "\n$APP is now running at: http://$IP:61208\n"
|
||||
}
|
||||
|
||||
# update on Debian/Ubuntu
|
||||
@@ -90,7 +98,7 @@ update_glances_debian() {
|
||||
msg_info "Updating $APP"
|
||||
cd /opt/glances
|
||||
source .venv/bin/activate
|
||||
$STD uv pip install --upgrade "glances[web]"
|
||||
uv pip install --upgrade "glances[web]" >/dev/null 2>&1
|
||||
deactivate
|
||||
systemctl restart glances
|
||||
msg_ok "Updated successfully!"
|
||||
@@ -108,13 +116,14 @@ uninstall_glances_debian() {
|
||||
# install on Alpine
|
||||
install_glances_alpine() {
|
||||
msg_info "Installing dependencies"
|
||||
$STD apk update
|
||||
apk update >/dev/null 2>&1
|
||||
$STD apk add --no-cache \
|
||||
gcc musl-dev linux-headers python3-dev \
|
||||
python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl
|
||||
python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl >/dev/null 2>&1
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
msg_info "Setting up Python + uv"
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
setup_uv PYTHON_VERSION="3.12"
|
||||
msg_ok "Setup Python + uv"
|
||||
|
||||
@@ -122,10 +131,10 @@ install_glances_alpine() {
|
||||
cd /opt
|
||||
mkdir -p glances
|
||||
cd glances
|
||||
$STD uv venv --clear
|
||||
uv venv --clear
|
||||
source .venv/bin/activate
|
||||
$STD uv pip install --upgrade pip wheel setuptools
|
||||
$STD uv pip install "glances[web]"
|
||||
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1
|
||||
uv pip install "glances[web]" >/dev/null 2>&1
|
||||
deactivate
|
||||
msg_ok "Installed $APP"
|
||||
|
||||
@@ -156,7 +165,7 @@ update_glances_alpine() {
|
||||
msg_info "Updating $APP"
|
||||
cd /opt/glances
|
||||
source .venv/bin/activate
|
||||
$STD uv pip install --upgrade "glances[web]"
|
||||
uv pip install --upgrade "glances[web]" >/dev/null 2>&1
|
||||
deactivate
|
||||
rc-service glances restart
|
||||
msg_ok "Updated successfully!"
|
||||
|
||||
+14
-8
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -24,7 +19,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "homebrew" "addon"
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -34,7 +29,18 @@ APP="homebrew"
|
||||
APP_TYPE="tools"
|
||||
INSTALL_PATH="/home/linuxbrew/.linuxbrew"
|
||||
|
||||
require_debian_like
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
echo -e "${CROSS} Alpine is not supported by Homebrew. Exiting."
|
||||
exit 1
|
||||
elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
||||
OS="Debian"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -75,7 +81,7 @@ function install() {
|
||||
msg_ok "Created user 'brew'"
|
||||
else
|
||||
msg_error "Cannot install Homebrew without a non-root user. Exiting."
|
||||
exit 254
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
msg_ok "Detected User: $BREW_USER"
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -32,12 +27,39 @@ APP="Immich Public Proxy"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/immich-proxy"
|
||||
CONFIG_PATH="/opt/immich-proxy/app"
|
||||
SERVICE_PATH="/etc/systemd/system/immich-proxy.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, $STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ _ __ ____
|
||||
/ _/___ ___ ____ ___ (_)____/ /_ / __ \_________ _ ____ __
|
||||
/ // __ `__ \/ __ `__ \/ / ___/ __ \______/ /_/ / ___/ __ \| |/_/ / / /
|
||||
_/ // / / / / / / / / / / / /__/ / / /_____/ ____/ / / /_/ /> </ /_/ /
|
||||
/___/_/ /_/ /_/_/ /_/ /_/_/\___/_/ /_/ /_/ /_/ \____/_/|_|\__, /
|
||||
/____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
msg_error "Alpine is not supported for ${APP}. Use Debian."
|
||||
exit 238
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/immich-proxy.service"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -61,13 +83,19 @@ function update() {
|
||||
systemctl stop immich-proxy.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
BACKUP_DIR="/opt/immich-public-proxy_backup"
|
||||
create_backup "$CONFIG_PATH"/.env "$CONFIG_PATH"/config.json
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH"/.env /tmp/ipp.env.bak 2>/dev/null || true
|
||||
cp "$CONFIG_PATH"/config.json /tmp/ipp.config.json.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Immich Public Proxy" "alangrainger/immich-public-proxy" "tarball" "latest" "$INSTALL_PATH"
|
||||
|
||||
restore_backup
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/ipp.env.bak "$CONFIG_PATH"/.env 2>/dev/null || true
|
||||
cp /tmp/ipp.config.json.bak "$CONFIG_PATH"/config.json 2>/dev/null || true
|
||||
rm -f /tmp/ipp.*.bak
|
||||
msg_ok "Restored configuration"
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
cd "$CONFIG_PATH"
|
||||
|
||||
+36
-10
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -32,12 +27,39 @@ APP="Jellystat"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/jellystat"
|
||||
CONFIG_PATH="/opt/jellystat/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/jellystat.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
__ ____ __ __
|
||||
/ /__ / / /_ _______/ /_____ _/ /_
|
||||
__ / / _ \/ / / / / / ___/ __/ __ `/ __/
|
||||
/ /_/ / __/ / / /_/ (__ ) /_/ /_/ / /_
|
||||
\____/\___/_/_/\__, /____/\__/\__,_/\__/
|
||||
/____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
|
||||
exit 238
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/jellystat.service"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -80,12 +102,16 @@ function update() {
|
||||
systemctl stop jellystat.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
BACKUP_DIR="/opt/jellystat_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/jellystat.env.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
|
||||
|
||||
restore_backup
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/jellystat.env.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/jellystat.env.bak
|
||||
msg_ok "Restored configuration"
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
cd "$INSTALL_PATH"
|
||||
|
||||
+61
-12
@@ -6,13 +6,8 @@
|
||||
# Source: https://komo.do/ | Github: https://github.com/moghtech/komodo
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
apt-get update >/dev/null 2>&1 || apk update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1 || apk add --no-cache 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)
|
||||
@@ -136,7 +131,25 @@ function update() {
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# DEPENDENCIES
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function ensure_openssl() {
|
||||
if command -v openssl &>/dev/null; then
|
||||
@@ -150,17 +163,53 @@ function ensure_openssl() {
|
||||
$STD apt-get install -y openssl
|
||||
else
|
||||
msg_error "openssl is required but could not be installed automatically."
|
||||
exit 237
|
||||
exit 10
|
||||
fi
|
||||
msg_ok "Installed openssl"
|
||||
}
|
||||
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
ensure_openssl
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
|
||||
ensure_openssl
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
ensure_openssl
|
||||
check_or_install_docker
|
||||
|
||||
echo -e "${TAB}Choose the database for Komodo:"
|
||||
echo -e "${TAB} 1) MongoDB (recommended)"
|
||||
@@ -243,7 +292,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
check_proxmox_host
|
||||
get_lxc_ip
|
||||
|
||||
# Declare variables used by find_compose_file
|
||||
|
||||
+89
-40
@@ -5,31 +5,74 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.netdata.cloud/ | Github: https://github.com/netdata/netdata
|
||||
|
||||
APP="Netdata"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ ____ __
|
||||
/ | / /__ / /_/ __ \____ _/ /_____ _
|
||||
/ |/ / _ \/ __/ / / / __ `/ __/ __ `/
|
||||
/ /| / __/ /_/ /_/ / /_/ / /_/ /_/ /
|
||||
/_/ |_/\___/\__/_____/\__,_/\__/\__,_/
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
silent() { "$@" >/dev/null 2>&1; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "netdata" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
set -e
|
||||
header_info
|
||||
echo "Loading..."
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
||||
|
||||
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||
# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0–9.x
|
||||
pve_check() {
|
||||
local PVE_VER
|
||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||
|
||||
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||
if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
|
||||
local MINOR="${BASH_REMATCH[1]}"
|
||||
if ((MINOR < 0 || MINOR > 9)); then
|
||||
msg_error "This version of Proxmox VE is not supported."
|
||||
msg_error "Supported: Proxmox VE version 8.0 – 8.9"
|
||||
exit 105
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for Proxmox VE 9.x: allow 9.0–9.x
|
||||
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# All other unsupported versions
|
||||
msg_error "This version of Proxmox VE is not supported."
|
||||
msg_error "Supported versions: Proxmox VE 8.0 – 8.9 or 9.0–9.x"
|
||||
exit 105
|
||||
}
|
||||
|
||||
detect_codename() {
|
||||
source /etc/os-release
|
||||
@@ -40,7 +83,7 @@ detect_codename() {
|
||||
CODENAME="${VERSION_CODENAME:-}"
|
||||
if [[ -z "$CODENAME" ]]; then
|
||||
msg_error "Could not detect Debian codename."
|
||||
exit 238
|
||||
exit 71
|
||||
fi
|
||||
echo "$CODENAME"
|
||||
}
|
||||
@@ -54,8 +97,9 @@ get_latest_repo_pkg() {
|
||||
}
|
||||
|
||||
install() {
|
||||
header_info
|
||||
while true; do
|
||||
read -r -p "Are you sure you want to install ${APP} on Proxmox VE host. Proceed(y/n)? " yn
|
||||
read -p "Are you sure you want to install NetData on Proxmox VE host. Proceed(y/n)? " yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
@@ -63,51 +107,56 @@ install() {
|
||||
esac
|
||||
done
|
||||
|
||||
read -r -p "Verbose mode? <y/N> " prompt
|
||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
|
||||
|
||||
CODENAME=$(detect_codename)
|
||||
REPO_URL="https://repo.netdata.cloud/repos/repoconfig/debian/${CODENAME}/"
|
||||
|
||||
msg_info "Setting up repository"
|
||||
$STD apt install -y debian-keyring
|
||||
$STD apt-get install -y debian-keyring
|
||||
PKG=$(get_latest_repo_pkg "$REPO_URL")
|
||||
if [[ -z "$PKG" ]]; then
|
||||
msg_error "Could not find netdata-repo package for Debian $CODENAME"
|
||||
exit 237
|
||||
fi
|
||||
TMP_DEB=$(mktemp --suffix=.deb)
|
||||
curl -fsSL "${REPO_URL}${PKG}" -o "$TMP_DEB"
|
||||
$STD dpkg -i "$TMP_DEB"
|
||||
rm -f "$TMP_DEB"
|
||||
curl -fsSL "${REPO_URL}${PKG}" -o "$PKG"
|
||||
$STD dpkg -i "$PKG"
|
||||
rm -f "$PKG"
|
||||
msg_ok "Set up repository"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
$STD apt update
|
||||
$STD apt install -y netdata
|
||||
msg_ok "Installed ${APP}"
|
||||
msg_info "Installing Netdata"
|
||||
$STD apt-get update
|
||||
$STD apt-get install -y netdata
|
||||
msg_ok "Installed Netdata"
|
||||
msg_ok "Completed successfully!\n"
|
||||
get_lxc_ip
|
||||
echo -e "\n${APP} should be reachable at${BL} http://${LOCAL_IP}:19999 ${CL}\n"
|
||||
echo -e "\n Netdata should be reachable at${BL} http://$(hostname -I | awk '{print $1}'):19999 ${CL}\n"
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
header_info
|
||||
read -r -p "Verbose mode? <y/N> " prompt
|
||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
|
||||
|
||||
msg_info "Uninstalling Netdata"
|
||||
systemctl stop netdata || true
|
||||
rm -rf /var/log/netdata /var/lib/netdata /var/cache/netdata /etc/netdata/go.d
|
||||
rm -rf /etc/apt/trusted.gpg.d/netdata-archive-keyring.gpg /etc/apt/sources.list.d/netdata.list
|
||||
$STD apt remove --purge -y netdata netdata-repo
|
||||
$STD apt-get remove --purge -y netdata netdata-repo
|
||||
systemctl daemon-reload
|
||||
$STD apt autoremove -y
|
||||
$STD userdel netdata || true
|
||||
msg_ok "Uninstalled ${APP}"
|
||||
msg_ok "Uninstalled Netdata"
|
||||
msg_ok "Completed successfully!\n"
|
||||
}
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
pve_check
|
||||
|
||||
OPTIONS=(Install "Install ${APP} on Proxmox VE"
|
||||
Uninstall "Uninstall ${APP} from Proxmox VE")
|
||||
OPTIONS=(Install "Install NetData on Proxmox VE"
|
||||
Uninstall "Uninstall NetData from Proxmox VE")
|
||||
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP}" \
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "NetData" \
|
||||
--menu "Select an option:" 10 58 2 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
case $CHOICE in
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -25,7 +20,6 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nextcloud-exp
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -37,6 +31,14 @@ BINARY_PATH="/usr/bin/nextcloud-exporter"
|
||||
CONFIG_PATH="/etc/nextcloud-exporter.env"
|
||||
SERVICE_PATH="/etc/systemd/system/nextcloud-exporter.service"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
+49
-113
@@ -5,131 +5,67 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://docs.olivetin.app/ | Github: https://github.com/OliveTin/OliveTin
|
||||
|
||||
APP="OliveTin"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ ___ _______
|
||||
/ __ \/ (_) _____/_ __(_)___
|
||||
/ / / / / / | / / _ \/ / / / __ \
|
||||
/ /_/ / / /| |/ / __/ / / / / / /
|
||||
\____/_/_/ |___/\___/_/ /_/_/ /_/
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
EOF
|
||||
}
|
||||
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="OliveTin"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "olivetin" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
set-e
|
||||
header_info
|
||||
ensure_usr_local_bin_persist
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl disable --now OliveTin &>/dev/null || true
|
||||
$STD apt remove -y olivetin
|
||||
rm -f "$HOME/.olivetin"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
if check_for_gh_release "olivetin" "OliveTin/OliveTin"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "olivetin" "OliveTin/OliveTin" "binary"
|
||||
systemctl restart OliveTin
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
msg_info "Installing ${APP}"
|
||||
fetch_and_deploy_gh_release "olivetin" "OliveTin/OliveTin" "binary"
|
||||
systemctl enable --now OliveTin &>/dev/null
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating update script"
|
||||
ensure_usr_local_bin_persist
|
||||
cat <<'EOF' >/usr/local/bin/update_olivetin
|
||||
#!/usr/bin/env bash
|
||||
# OliveTin Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/olivetin.sh)"
|
||||
EOF
|
||||
chmod +x /usr/local/bin/update_olivetin
|
||||
msg_ok "Created update script (/usr/local/bin/update_olivetin)"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://${IP}:1337${CL} \n"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
if command -v olivetin &>/dev/null; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 233
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -d "$HOME" && -f "$HOME/.olivetin" ]] || command -v olivetin &>/dev/null; then
|
||||
msg_warn "${APP} is already installed."
|
||||
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
|
||||
|
||||
while true; do
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
unset _HEADER_SHOWN
|
||||
header_info
|
||||
|
||||
install
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
if ! command -v curl &>/dev/null; then
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
curl -fsSL "https://github.com/OliveTin/OliveTin/releases/latest/download/OliveTin_linux_amd64.deb" -o $(basename "https://github.com/OliveTin/OliveTin/releases/latest/download/OliveTin_linux_amd64.deb")
|
||||
dpkg -i OliveTin_linux_amd64.deb &>/dev/null
|
||||
systemctl enable --now OliveTin &>/dev/null
|
||||
rm OliveTin_linux_amd64.deb
|
||||
msg_ok "Installed ${APP} on $hostname"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://$IP:1337${CL} \n"
|
||||
|
||||
+65
-65
@@ -5,36 +5,39 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.phpmyadmin.net/ | Github: https://github.com/phpmyadmin/phpmyadmin
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ __ __ ___ ___ __ _
|
||||
/ __ \/ /_ ____ / |/ /_ __/ | ____/ /___ ___ (_)___
|
||||
/ /_/ / __ \/ __ \/ /|_/ / / / / /| |/ __ / __ `__ \/ / __ \
|
||||
/ ____/ / / / /_/ / / / / /_/ / ___ / /_/ / / / / / / / / / /
|
||||
/_/ /_/ /_/ .___/_/ /_/\__, /_/ |_\__,_/_/ /_/ /_/_/_/ /_/
|
||||
/_/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="phpMyAdmin"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_DIR_DEBIAN="/var/www/html/phpMyAdmin"
|
||||
INSTALL_DIR_ALPINE="/usr/share/phpmyadmin"
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "phpmyadmin" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
|
||||
# Detect OS
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
@@ -44,20 +47,24 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
INSTALL_DIR="$INSTALL_DIR_ALPINE"
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
PKG_MANAGER_INSTALL="apt install -y"
|
||||
PKG_MANAGER_INSTALL="apt-get install -y"
|
||||
PKG_QUERY="dpkg -l"
|
||||
INSTALL_DIR="$INSTALL_DIR_DEBIAN"
|
||||
else
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}${1}...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}${1}${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}${1}${CL}"; }
|
||||
|
||||
function check_internet() {
|
||||
if ! command -v curl &>/dev/null; then
|
||||
$STD apt update
|
||||
$STD apt install -y curl
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
msg_info "Checking Internet connectivity to GitHub"
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
|
||||
@@ -96,7 +103,7 @@ function install_php_and_modules() {
|
||||
done
|
||||
if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then
|
||||
msg_info "Installing missing PHP packages: ${MISSING_PACKAGES[*]}"
|
||||
if ! $STD apt update || ! $STD apt install -y "${MISSING_PACKAGES[@]}"; then
|
||||
if ! apt-get update &>/dev/null || ! apt-get install -y "${MISSING_PACKAGES[@]}" &>/dev/null; then
|
||||
msg_error "Failed to install required PHP modules. Exiting."
|
||||
exit 237
|
||||
fi
|
||||
@@ -106,41 +113,30 @@ function install_php_and_modules() {
|
||||
fi
|
||||
else
|
||||
msg_info "Installing Lighttpd and PHP for Alpine"
|
||||
$STD $PKG_MANAGER_INSTALL \
|
||||
lighttpd \
|
||||
php \
|
||||
php-fpm \
|
||||
php-session \
|
||||
php-json \
|
||||
php-mysqli \
|
||||
curl \
|
||||
tar \
|
||||
openssl
|
||||
$PKG_MANAGER_INSTALL lighttpd php php-fpm php-session php-json php-mysqli curl tar openssl &>/dev/null
|
||||
msg_ok "Installed Lighttpd and PHP"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_phpmyadmin() {
|
||||
msg_info "Fetching latest phpMyAdmin release from GitHub"
|
||||
LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
|
||||
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4)
|
||||
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
|
||||
if [[ -z "$LATEST_VERSION" ]]; then
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="5.2.2"
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="RELEASE_5_2_2"
|
||||
fi
|
||||
msg_ok "Latest version: $LATEST_VERSION"
|
||||
|
||||
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
|
||||
msg_info "Downloading ${TARBALL_URL}"
|
||||
tarball=$(mktemp)
|
||||
if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
|
||||
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
|
||||
msg_error "Download failed: $TARBALL_URL"
|
||||
exit 115
|
||||
fi
|
||||
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
|
||||
rm -f "$tarball"
|
||||
tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C "$INSTALL_DIR"
|
||||
}
|
||||
|
||||
function configure_phpmyadmin() {
|
||||
@@ -227,43 +223,47 @@ function uninstall_phpmyadmin() {
|
||||
|
||||
function update_phpmyadmin() {
|
||||
msg_info "Fetching latest phpMyAdmin release from GitHub"
|
||||
LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
|
||||
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4)
|
||||
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
|
||||
|
||||
if [[ -z "$LATEST_VERSION" ]]; then
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="5.2.2"
|
||||
fi
|
||||
msg_ok "Latest version: $LATEST_VERSION"
|
||||
|
||||
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
|
||||
msg_info "Downloading ${TARBALL_URL}"
|
||||
tarball=$(mktemp)
|
||||
|
||||
if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
|
||||
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
|
||||
msg_error "Download failed: $TARBALL_URL"
|
||||
exit 115
|
||||
fi
|
||||
|
||||
BACKUP_DIR="/opt/phpmyadmin_backup"
|
||||
create_backup \
|
||||
"$INSTALL_DIR/config.inc.php" \
|
||||
"$INSTALL_DIR/upload" \
|
||||
"$INSTALL_DIR/save" \
|
||||
"$INSTALL_DIR/tmp" \
|
||||
"$INSTALL_DIR/themes"
|
||||
BACKUP_DIR="/tmp/phpmyadmin-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
BACKUP_ITEMS=("config.inc.php" "upload" "save" "tmp" "themes")
|
||||
|
||||
tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
|
||||
rm -f "$tarball"
|
||||
msg_info "Backing up existing phpMyAdmin data"
|
||||
for item in "${BACKUP_ITEMS[@]}"; do
|
||||
[[ -e "$INSTALL_DIR/$item" ]] && cp -a "$INSTALL_DIR/$item" "$BACKUP_DIR/" && echo " ↪︎ $item"
|
||||
done
|
||||
msg_ok "Backup completed: $BACKUP_DIR"
|
||||
|
||||
tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C "$INSTALL_DIR"
|
||||
msg_ok "Extracted phpMyAdmin $LATEST_VERSION"
|
||||
|
||||
restore_backup
|
||||
msg_info "Restoring preserved files"
|
||||
for item in "${BACKUP_ITEMS[@]}"; do
|
||||
[[ -e "$BACKUP_DIR/$item" ]] && cp -a "$BACKUP_DIR/$item" "$INSTALL_DIR/" && echo " ↪︎ $item restored"
|
||||
done
|
||||
msg_ok "Restoration completed"
|
||||
|
||||
configure_phpmyadmin
|
||||
}
|
||||
|
||||
if is_phpmyadmin_installed; then
|
||||
msg_warn "${APP} is already installed at ${INSTALL_DIR}."
|
||||
echo -e "${YW}⚠️ ${APP} is already installed at ${INSTALL_DIR}.${CL}"
|
||||
read -r -p "Would you like to Update (1), Uninstall (2) or Cancel (3)? [1/2/3]: " action
|
||||
action="${action//[[:space:]]/}"
|
||||
case "$action" in
|
||||
@@ -275,11 +275,11 @@ if is_phpmyadmin_installed; then
|
||||
uninstall_phpmyadmin
|
||||
;;
|
||||
3)
|
||||
msg_warn "Action cancelled. Exiting."
|
||||
echo -e "${YW}⚠️ Action cancelled. Exiting.${CL}"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
msg_warn "Invalid input. Exiting."
|
||||
echo -e "${YW}⚠️ Invalid input. Exiting.${CL}"
|
||||
exit 112
|
||||
;;
|
||||
esac
|
||||
@@ -292,12 +292,12 @@ else
|
||||
install_phpmyadmin
|
||||
configure_phpmyadmin
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}"
|
||||
else
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}/${CL}"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/${CL}"
|
||||
fi
|
||||
else
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/portainer/portainer
|
||||
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
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "portainer" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================
|
||||
APP="Portainer"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/portainer"
|
||||
COMPOSE_FILE="${INSTALL_PATH}/compose.yaml"
|
||||
DEFAULT_PORT=9443
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# 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_portainer"
|
||||
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 10
|
||||
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 10
|
||||
fi
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK EXISTING CONTAINER
|
||||
# ==============================================================================
|
||||
function check_existing_container() {
|
||||
# Guards against clobbering a Portainer container not managed by this addon
|
||||
# (e.g. Business/Enterprise Edition installed manually or via the legacy docker.sh flow)
|
||||
if docker ps -a --format '{{.Names}}' | grep -q '^portainer$'; then
|
||||
msg_error "A container named 'portainer' already exists but is not managed by this addon."
|
||||
msg_error "This may be a Portainer Business/Enterprise Edition install or a manual setup."
|
||||
msg_error "Remove/rename that container first, or manage it manually. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_docker
|
||||
check_existing_container
|
||||
|
||||
msg_info "Creating install directory"
|
||||
mkdir -p "$INSTALL_PATH"
|
||||
msg_ok "Created ${INSTALL_PATH}"
|
||||
|
||||
msg_info "Downloading Docker Compose file"
|
||||
curl -fsSL "https://downloads.portainer.io/ce-sts/portainer-compose.yaml" -o "$COMPOSE_FILE"
|
||||
msg_ok "Downloaded Docker Compose file"
|
||||
|
||||
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_portainer
|
||||
#!/usr/bin/env bash
|
||||
# Portainer Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)"
|
||||
UPDATEEOF
|
||||
chmod +x /usr/local/bin/update_portainer
|
||||
msg_ok "Created update script (/usr/local/bin/update_portainer)"
|
||||
|
||||
echo ""
|
||||
msg_ok "${APP} is reachable at: ${BL}https://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
|
||||
echo ""
|
||||
msg_warn "On first access, you'll be prompted to create an admin account."
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# 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 233
|
||||
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} - Portainer (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
|
||||
@@ -5,16 +5,6 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/hansmi/prometheus-paperless-exporter
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -25,7 +15,6 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "prometheus-pa
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -38,6 +27,14 @@ CONFIG_PATH="/etc/prometheus-paperless-ngx-exporter/config.env"
|
||||
SERVICE_PATH="/etc/systemd/system/prometheus-paperless-ngx-exporter.service"
|
||||
AUTH_TOKEN_FILE="/etc/prometheus-paperless-ngx-exporter/paperless_auth_token_file"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
+79
-126
@@ -5,123 +5,77 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://pyenv.run/ | Github: https://github.com/pyenv/pyenv
|
||||
|
||||
APP="pyenv"
|
||||
APP_TYPE="addon"
|
||||
set -e
|
||||
YW=$(echo "\033[33m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✓${CL}"
|
||||
CROSS="${RD}✗${CL}"
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pyenv" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
export PYENV_ROOT="${HOME}/.pyenv"
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
$STD apt update
|
||||
|
||||
# Official Python build dependencies for Debian/Ubuntu
|
||||
# https://github.com/pyenv/pyenv/wiki#suggested-build-environment
|
||||
PYENV_DEPS=(
|
||||
build-essential
|
||||
libssl-dev
|
||||
zlib1g-dev
|
||||
libbz2-dev
|
||||
libreadline-dev
|
||||
libsqlite3-dev
|
||||
curl
|
||||
git
|
||||
xz-utils
|
||||
tk-dev
|
||||
libxml2-dev
|
||||
libxmlsec1-dev
|
||||
libffi-dev
|
||||
liblzma-dev
|
||||
)
|
||||
|
||||
# Extras for the optional Home Assistant / ESPHome installs below (Pillow et al.)
|
||||
PYENV_DEPS+=(make llvm libjpeg-dev libpcap-dev libopenjp2-7)
|
||||
|
||||
# These were renamed between releases (libtiff5 is gone on Debian 13 / Ubuntu 24.04),
|
||||
# so take whichever variant the distro actually ships
|
||||
for candidates in "libncurses-dev libncursesw5-dev" "libtiff-dev libtiff5-dev" "libturbojpeg0-dev libturbojpeg-dev"; do
|
||||
for pkg in $candidates; do
|
||||
if apt-cache show "$pkg" &>/dev/null; then
|
||||
PYENV_DEPS+=("$pkg")
|
||||
break
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
msg_error "Can't Install on Proxmox "
|
||||
exit
|
||||
fi
|
||||
done
|
||||
done
|
||||
msg_info "Installing pyenv"
|
||||
apt-get install -y \
|
||||
make \
|
||||
build-essential \
|
||||
libjpeg-dev \
|
||||
libpcap-dev \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
libbz2-dev \
|
||||
libreadline-dev \
|
||||
libsqlite3-dev \
|
||||
autoconf \
|
||||
git \
|
||||
curl \
|
||||
sudo \
|
||||
llvm \
|
||||
libncursesw5-dev \
|
||||
xz-utils \
|
||||
tk-dev \
|
||||
libxml2-dev \
|
||||
libxmlsec1-dev \
|
||||
libffi-dev \
|
||||
libopenjp2-7 \
|
||||
libtiff5 \
|
||||
libturbojpeg0-dev \
|
||||
liblzma-dev &>/dev/null
|
||||
|
||||
install_packages_with_retry "${PYENV_DEPS[@]}"
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
# The upstream installer refuses to run when PYENV_ROOT already exists
|
||||
if [[ -d "$PYENV_ROOT" ]]; then
|
||||
msg_ok "${APP} is already installed at ${PYENV_ROOT}"
|
||||
else
|
||||
msg_info "Installing ${APP}"
|
||||
# Official installer - also sets up the pyenv-doctor/update/virtualenv plugins
|
||||
$STD bash <(curl -fsSL https://pyenv.run)
|
||||
msg_ok "Installed ${APP}"
|
||||
fi
|
||||
|
||||
# Shell setup per upstream docs. On Debian-based systems ~/.profile prepends the
|
||||
# per-user bin dirs *after* sourcing ~/.bashrc, so both files need the init call.
|
||||
msg_info "Configuring shell environment"
|
||||
for rc in "${HOME}/.bashrc" "${HOME}/.profile"; do
|
||||
[[ -f "$rc" ]] || touch "$rc"
|
||||
if ! grep -q 'PYENV_ROOT' "$rc"; then
|
||||
cat >>"$rc" <<'EOF'
|
||||
|
||||
# pyenv
|
||||
export PYENV_ROOT="$HOME/.pyenv"
|
||||
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
eval "$(pyenv init - bash)"
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
msg_ok "Configured shell environment"
|
||||
|
||||
# Activate pyenv for the remainder of this script
|
||||
export PATH="${PYENV_ROOT}/bin:$PATH"
|
||||
set +Eeuo pipefail
|
||||
eval "$(pyenv init - bash)"
|
||||
set -Eeuo pipefail
|
||||
|
||||
# pyenv resolves a version prefix to the latest release in that line, so pinning
|
||||
# a patch level (the old 3.11.1) is neither needed nor portable across distros.
|
||||
#
|
||||
# 3.14 is the only series all three optional payloads below agree on:
|
||||
# Home Assistant Core >= 3.14.2
|
||||
# ESPHome >= 3.12.0, < 3.15
|
||||
# python-matter-server >= 3.12
|
||||
# (3.11 has been security-fix-only since 2024 and is EOL in 10/2027.)
|
||||
PYTHON_SERIES="3.14"
|
||||
msg_info "Installing Python ${PYTHON_SERIES} (latest patch release)"
|
||||
$STD pyenv install -s "$PYTHON_SERIES"
|
||||
pyenv global "$PYTHON_SERIES"
|
||||
msg_ok "Installed Python $(pyenv version-name)"
|
||||
git clone https://github.com/pyenv/pyenv.git ~/.pyenv &>/dev/null
|
||||
set +e
|
||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc
|
||||
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >>~/.bashrc
|
||||
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >>~/.bashrc
|
||||
msg_ok "Installed pyenv"
|
||||
. ~/.bashrc
|
||||
set -e
|
||||
msg_info "Installing Python 3.11.1"
|
||||
pyenv install 3.11.1 &>/dev/null
|
||||
pyenv global 3.11.1
|
||||
msg_ok "Installed Python 3.11.1"
|
||||
read -r -p "Would you like to install Home Assistant Beta? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Home Assistant Beta"
|
||||
@@ -141,13 +95,13 @@ EOF
|
||||
cd /srv/homeassistant
|
||||
python3 -m venv .
|
||||
source bin/activate
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip3 install psycopg2-binary
|
||||
$STD pip3 install --pre homeassistant
|
||||
python3 -m pip install wheel &>/dev/null
|
||||
pip3 install --upgrade pip &>/dev/null
|
||||
pip3 install psycopg2-binary &>/dev/null
|
||||
pip3 install --pre homeassistant &>/dev/null
|
||||
systemctl enable homeassistant &>/dev/null
|
||||
msg_ok "Installed Home Assistant Beta"
|
||||
echo -e " Go to ${LOCAL_IP}:8123"
|
||||
echo -e " Go to $(hostname -I | awk '{print $1}'):8123"
|
||||
hass
|
||||
fi
|
||||
|
||||
@@ -158,9 +112,9 @@ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
cd /srv/esphome
|
||||
python3 -m venv .
|
||||
source bin/activate
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip3 install --pre esphome
|
||||
python3 -m pip install wheel &>/dev/null
|
||||
pip3 install --upgrade pip &>/dev/null
|
||||
pip3 install --pre esphome &>/dev/null
|
||||
cat <<EOF >/srv/esphome/start.sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
@@ -189,26 +143,25 @@ WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable --now esphomedashboard &>/dev/null
|
||||
msg_ok "Installed ESPHome Beta"
|
||||
echo -e " Go to ${LOCAL_IP}:6052"
|
||||
echo -e " Go to $(hostname -I | awk '{print $1}'):6052"
|
||||
exec $SHELL
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to install Matter-Server (Beta)? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Matter Server"
|
||||
$STD apt install -y \
|
||||
apt-get install -y \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libgirepository1.0-dev \
|
||||
libpango1.0-dev \
|
||||
libgif-dev \
|
||||
g++
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip install python-matter-server[server]
|
||||
g++ &>/dev/null
|
||||
python3 -m pip install wheel
|
||||
pip3 install --upgrade pip
|
||||
pip install python-matter-server[server]
|
||||
msg_ok "Installed Matter Server"
|
||||
echo -e "Start server > python -m matter_server.server"
|
||||
fi
|
||||
msg_ok "\nFinished\n"
|
||||
exec $SHELL
|
||||
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
|
||||
+56
-3
@@ -35,6 +35,55 @@ DEFAULT_PORT=80
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -75,7 +124,7 @@ function update() {
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
ensure_docker
|
||||
check_or_install_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
$STD apt-get update
|
||||
@@ -125,9 +174,13 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
msg_error "${APP} does not support Alpine Linux. Please use a Debian or Ubuntu based LXC."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
require_debian_like
|
||||
confirm_not_pve_host
|
||||
check_proxmox_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -7,14 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
@@ -25,7 +20,6 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "sparkyfitness
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -37,6 +31,14 @@ CONFIG_PATH="/etc/sparkyfitness-garmin/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/sparkyfitness-garmin.service"
|
||||
DEFAULT_PORT=8000
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# SparkyFitness LXC DETECTION
|
||||
# ==============================================================================
|
||||
|
||||
+46
-38
@@ -5,53 +5,61 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.webmin.com/ | Github: https://github.com/webmin/webmin
|
||||
|
||||
APP="Webmin"
|
||||
APP_TYPE="addon"
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ _
|
||||
| | /| / /__ / / __ _ (_)__
|
||||
| |/ |/ / -_) _ \/ ' \/ / _ \
|
||||
|__/|__/\__/_.__/_/_/_/_/_//_/
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
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)
|
||||
EOF
|
||||
}
|
||||
set -eEuo pipefail
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✓${CL}"
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
|
||||
msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "webmin" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} Installer" --yesno "This Will Install ${APP} on this LXC Container. Proceed?" 10 58
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Webmin Installer" --yesno "This Will Install Webmin on this LXC Container. Proceed?" 10 58
|
||||
|
||||
msg_info "Installing Prerequisites"
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
libnet-ssleay-perl \
|
||||
libauthen-pam-perl \
|
||||
libio-pty-perl \
|
||||
unzip \
|
||||
shared-mime-info \
|
||||
curl
|
||||
apt update &>/dev/null
|
||||
apt-get -y install libnet-ssleay-perl libauthen-pam-perl libio-pty-perl unzip shared-mime-info curl &>/dev/null
|
||||
msg_ok "Installed Prerequisites"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
fetch_and_deploy_gh_release "webmin" "webmin/webmin" "binary" "latest" "/opt/webmin" "webmin_*_all.deb"
|
||||
LATEST=$(curl -fsSL https://api.github.com/repos/webmin/webmin/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
|
||||
|
||||
msg_info "Downloading Webmin"
|
||||
curl -fsSL "https://github.com/webmin/webmin/releases/download/$LATEST/webmin_${LATEST}_all.deb" -o $(basename "https://github.com/webmin/webmin/releases/download/$LATEST/webmin_${LATEST}_all.deb")
|
||||
msg_ok "Downloaded Webmin"
|
||||
|
||||
msg_info "Installing Webmin"
|
||||
dpkg -i webmin_${LATEST}_all.deb &>/dev/null
|
||||
/usr/share/webmin/changepass.pl /etc/webmin root root &>/dev/null
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
get_lxc_ip
|
||||
echo -e "Successfully Installed!! ${APP} should be reachable by going to ${BL}https://${LOCAL_IP}:10000${CL}"
|
||||
rm -rf /root/webmin_${LATEST}_all.deb
|
||||
msg_ok "Installed Webmin"
|
||||
|
||||
IP=$(hostname -I | cut -f1 -d ' ')
|
||||
echo -e "Successfully Installed!! Webmin should be reachable by going to ${BL}https://${IP}:10000${CL}"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user