Compare commits

..

50 Commits

Author SHA1 Message Date
MickLesk 6ad7dda1ec refactor: use shared get_lxc_ip and get_latest_github_release helpers in addon scripts
- pyenv.sh, webmin.sh, netdata.sh: replace manual hostname -I parsing with get_lxc_ip/$LOCAL_IP
- phpmyadmin.sh: replace manual curl|grep|cut GitHub API version lookup with get_latest_github_release
2026-08-01 23:20:13 +02:00
MickLesk fc21e2c458 fix shellcheck 2026-08-01 23:13:43 +02:00
MickLesk 7b7d5c4fdc refactor: enhance error handling and messaging in all-templates script 2026-08-01 23:08:54 +02:00
MickLesk e028f3eb1b refactor: harmonize error handling and messaging in add-netbird-lxc and add-tailscale-lxc scripts 2026-08-01 23:04:53 +02:00
MickLesk 308ef17283 refactor: harmonize architecture detection and improve installation scripts for addons 2026-08-01 22:54:09 +02:00
MickLesk 0fb07d03e7 filebrowser-quantum: generate TMP_BIN via mktemp at use, not fixed PID-based path 2026-08-01 22:37:50 +02:00
MickLesk 084706a3d5 use create_backup und restore_backup 2026-08-01 22:35:32 +02:00
MickLesk cb58c616f7 refactor: coder-code-server GH-release binary install + multiline apt installs
- coder-code-server.sh: use fetch_and_deploy_gh_release (binary mode) + check_for_gh_release, add uninstall/update functions, update script + type=update handling
- copyparty.sh, filebrowser.sh, filebrowser-quantum.sh: format multi-package installs multiline
2026-08-01 22:29:20 +02:00
MickLesk 89e43f2753 add updater for olivetin 2026-08-01 22:26:05 +02:00
MickLesk 63434d9a0f refactor olivetin 2026-08-01 22:24:43 +02:00
MickLesk 7373c26b7f refactor olivethin 2026-08-01 22:21:45 +02:00
MickLesk d5d336698e switch to apt from apt-get 2026-08-01 22:20:27 +02:00
MickLesk a686666abd adguard use ip function 2026-08-01 22:16:10 +02:00
MickLesk bedc73a049 switch to apt in coder 2026-08-01 22:15:29 +02:00
MickLesk 92b7155ff9 refactor: complete addon harmonization (filebrowser-quantum, glances, olivetin, phpmyadmin, coder-code-server polish)
- Remove local get_lxc_ip() shadow in glances.sh, use core.func version
- Fix double header_info() call in olivetin.sh with _HEADER_SHOWN reset
- Add core.func/tools.func/error_handler.func sourcing to phpmyadmin.sh
- Replace unsafe hostname -I fallback with get_lxc_ip everywhere
- Use $STD for command execution and shared msg_info/msg_ok/msg_error/msg_warn
- All files verified clean via shellcheck (only expected SC1090 noise)
2026-08-01 22:06:30 +02:00
MickLesk 5356ce7dcc refactor coder-code crowdsec filebrowser 2026-08-01 21:59:28 +02:00
MickLesk 566cbf736d harmonize headers 2026-08-01 21:53:45 +02:00
community-scripts-pr-app[bot] 382ef231d8 Update CHANGELOG.md (#16199)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-01 19:19:51 +00:00
community-scripts-pr-app[bot] de122d075f Update CHANGELOG.md (#16198)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-01 19:19:37 +00:00
Sam Heinz cffbe03b20 Update bazarr-install.sh (#16191) 2026-08-01 21:19:28 +02:00
community-scripts-pr-app[bot] f11aab9f17 Update CHANGELOG.md (#16197)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-01 19:19:15 +00:00
Sam Heinz f12751cbd9 add CLEANUPARR_CONFIG_PATH, CLEANUPARR_LOGS_PATH vars (#16193) 2026-08-01 21:19:08 +02:00
Sam Heinz 73b804bce7 fix romm missing 7z (#16194) 2026-08-01 21:18:48 +02:00
MickLesk 5b65310d62 Update build.func 2026-07-31 14:13:45 +02:00
community-scripts-pr-app[bot] 4a92a434e4 Update CHANGELOG.md (#16178)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-31 07:46:59 +00:00
CanbiZ (MickLesk) 81fd7ef01a Docmost: cleanup folder at update (#16177) 2026-07-31 09:46:30 +02:00
community-scripts-pr-app[bot] fdb029403d Update CHANGELOG.md (#16176)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-31 05:49:49 +00:00
Slaviša Arežina 304e73cd18 Firecrawl: Add dependency (#16174)
* Add deps

* formatting
2026-07-31 07:49:17 +02:00
community-scripts-pr-app[bot] f8bdd424eb Update CHANGELOG.md (#16171)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 18:05:58 +00:00
Chris 70685ae8c3 Immich: Pin version to 3.1.0 (#16170)
* Immich: Pin version to 3.1.0

* Add countryInfo.txt to GeoNames data
2026-07-30 20:05:25 +02:00
community-scripts-pr-app[bot] c4ae4d99e4 Update CHANGELOG.md (#16168)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 12:41:25 +00:00
CanbiZ (MickLesk) d24422a533 tools.func: support dynamic gitlab URL | add setup_mysql_db function (#16166)
* tools.func: support dynamic gitlab URL

* Update tools.func

* Update tools.func

* restore meilisearch fix
2026-07-30 14:40:59 +02:00
community-scripts-pr-app[bot] d7bc6b5967 Update CHANGELOG.md (#16163)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:51:30 +00:00
Tim Moore 8045921784 Medusa: convert the non-free unrar source to deb822 format (#16093)
Follow-up to #16072, as requested in review.

Converts the one-line non-free.list entry to a deb822 non-free.sources
block matching mylar3 and sabnzbd, and renames the cleanup rm to match
the new filename.

Also drops the redundant main and contrib components, which the base
debian.sources already provides. Declaring them a second time made apt
emit "Target Packages ... is configured multiple times" warnings on
every build; only non-free is needed for unrar.

Co-authored-by: Tim Moore <tim.moore@ingenuity.com.au>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 10:51:00 +02:00
Michel Roegl-Brunner 089bcd1c09 Revise pull request template for AI compliance
Updated the pull request template to include AI assistance confirmation and additional instructions for AI-generated scripts.
2026-07-30 10:49:28 +02:00
community-scripts-pr-app[bot] b85de433db Update CHANGELOG.md (#16162)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:37:40 +00:00
Darkatek7 763732fc5b romm: remove stale 1.x alembic migrations on update (#16101)
* fix(romm): remove stale 1.x alembic migrations on update

RomM releases before v2.4 shipped dot-version migration files
(1.6.2_.py, 1.7.1_.py, 1.8_.py, 1.8.1_.py, 1.8.2_.py, 1.8.3_.py,
2.0.0_.py) alongside the 4-digit series. When the romm app is
upgraded from a pre-v2.4 install to a current release, these
files survive in /opt/romm/backend/alembic/versions/ and cause
alembic to fail with 'Multiple head revisions are present for
given argument head', preventing the backend from starting.

Add a defensive cleanup step in the update function that runs
right after fetch_and_deploy_gh_release. The cleanup removes any
leftover 1.x and 2.0.0_ migration files plus cached __pycache__
directories. It is a no-op on clean installs of the current
release, and only affects files in the alembic/versions/ folder.

* Apply suggestion from @CrazyWolf13

Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>

---------

Co-authored-by: Sam Heinz <sam@samheinz.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-07-30 10:37:17 +02:00
community-scripts-pr-app[bot] e456b1fc96 Update CHANGELOG.md (#16161)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:31:38 +00:00
CanbiZ (MickLesk) 30ab4a612d core: add configurable host CA inheritance during bootstrap (#15889)
* Add host CA inheritance for container builds

Introduces `var_inherit_host_ca` (default `auto`) across variable loading, validation, defaults, and persisted app vars. The advanced settings flow now includes a dedicated Host CA Inheritance step and surfaces the selection in the final summary.

Adds `_apply_host_ca_certs_in_container()` to copy host certificates from `/usr/local/share/ca-certificates/*.crt` into the container and refresh trust with `update-ca-certificates` when available. This runs during container setup after proxy configuration, with safe no-op behavior when no host certs exist or inheritance is disabled.

* Warn when host CA inheritance is disabled

Changes the log level from info to warning when host CA inheritance is skipped by configuration, and includes the number of host certificates detected. This makes intentional skips more visible while still showing useful context.

* core: make host CA inheritance opt-in (default no)

Addresses review feedback: default to 'no' instead of 'auto' so certs are
only inherited when explicitly enabled in advanced mode, preserving LXC
isolation by default.

---------

Co-authored-by: michel.roegl-brunner@htl-braunau.at <michel.roegl-brunner@htl-braunau.at>
2026-07-30 10:31:09 +02:00
community-scripts-pr-app[bot] c9bddaadc0 Update CHANGELOG.md (#16160)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:24:28 +00:00
push-app-to-main[bot] a1cc2351d7 Firecrawl (#16156)
* Add firecrawl (ct)

* Remove configuration file echo from firecrawl.sh

Removed configuration file output from the script.

* Refactor installation script for Firecrawl

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
2026-07-30 10:23:54 +02:00
community-scripts-pr-app[bot] 3157679ffe Update CHANGELOG.md (#16159)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:22:57 +00:00
push-app-to-main[bot] 4d311e03df OmniRoute (#16155)
* Add omniroute (ct)

* Update omniroute.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-07-30 10:22:29 +02:00
community-scripts-pr-app[bot] 2f8cb52962 Update CHANGELOG.md (#16157)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-30 08:07:27 +00:00
push-app-to-main[bot] 39d78754fa PegaProx (#16154)
* Add pegaprox (ct)

* Update pegaprox.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-07-30 10:06:57 +02:00
community-scripts-pr-app[bot] 09c11fdecf Update CHANGELOG.md (#16152)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-29 21:02:10 +00:00
community-scripts-pr-app[bot] e562ab6128 Update CHANGELOG.md (#16151)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-29 15:58:45 +00:00
CanbiZ (MickLesk) b5a9011581 Bichon: Migration for V2 Release (#16145) 2026-07-29 17:58:04 +02:00
community-scripts-pr-app[bot] 450a5948ec Update CHANGELOG.md (#16150)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-29 12:11:34 +00:00
CanbiZ (MickLesk) 6ff1e95334 core: Harden remote func bootstrapping with dns issues (#16146)
* Harden remote func bootstrapping

Replace bare `source <(curl ...)` calls with a `_bootstrap_source` helper that validates both the download exit code and the presence of a probe function after sourcing. This prevents silent failures when DNS is not yet available in a freshly booted container or when a download fails mid-stream. Applies to build.func, install.func, and alpine-install.func. Also adds retry flags and a connect timeout to curl/wget.

* Refactor bootstrap error handling with helper

Extract repeated fatal-error logic into a `_bootstrap_die` helper across alpine-install.func, build.func, and install.func. The helper uses `msg_error` when available, falling back to stderr, then exits with code 115. Inline error blocks are replaced with cleaner one-liner `|| _bootstrap_die` calls.
2026-07-29 14:11:08 +02:00
46 changed files with 1751 additions and 993 deletions
+11 -1
View File
@@ -1,5 +1,5 @@
<!--🛑 New scripts must be submitted to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) for testing. <!--🛑 New scripts must be submitted to [ProxmoxVED](https://github.com/community-scripts/ProxmoxVED) for testing.
PRs without prior testing will be closed. --> 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.-->
## ✍️ Description ## ✍️ Description
@@ -16,6 +16,16 @@ 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) ## 🛠️ Type of Change (**X** in brackets)
- [ ] 🐞 **Bug fix** Resolves an issue without breaking functionality. - [ ] 🐞 **Bug fix** Resolves an issue without breaking functionality.
+59 -2
View File
@@ -508,16 +508,73 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details> </details>
## 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 ## 2026-07-29
### 🚀 Updated Scripts ### 🚀 Updated Scripts
- backup virtual printer in bambuddy [@asylumexp](https://github.com/asylumexp) ([#16142](https://github.com/community-scripts/ProxmoxVE/pull/16142))
- #### 🐞 Bug Fixes - #### 🐞 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)) - 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 ## 2026-07-28
### 🚀 Updated Scripts ### 🚀 Updated Scripts
+32 -46
View File
@@ -34,26 +34,23 @@ function update_script() {
CURRENT_VERSION=$(cat /root/.bichon) CURRENT_VERSION=$(cat /root/.bichon)
fi fi
MIGRATE_V1=0 if [[ $CURRENT_VERSION != 1.* && $CURRENT_VERSION != 2.* ]]; then
if [[ $CURRENT_VERSION == 0.* ]]; then msg_error "Installed ${APP} version (${CURRENT_VERSION}) is too old for an automatic update to v2.x."
MIGRATE_V1=1 msg_error "Please create a new ${APP} container and migrate your data manually."
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | sed 's/%//') msg_error "Guide: https://github.com/rustmailer/bichon/wiki/Bichon-v2.x-Migration-Guide"
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 exit
fi fi
fi
RAM_TOTAL=$(free -m | awk '/^Mem:/{print $2}') MIGRATE_V2=0
if [ "$RAM_TOTAL" -lt 2000 ]; then if [[ $CURRENT_VERSION == 1.* ]]; then
echo -e "\n${RD}Warning: LXC has less than 2GB of RAM allocated (${RAM_TOTAL}MB).${CL}" MIGRATE_V2=1
echo -e "${RD}Bichon v1 data migration consumes significant memory and may crash if insufficient.${CL}" STORAGE_KB=$(du -sk /opt/bichon-data/bichon-storage 2>/dev/null | awk '{print $1}')
read -r -p "Are you sure you want to proceed with the update? (y/N): " proceed_ram FREE_KB=$(df -Pk /opt/bichon-data | awk 'NR==2 {print $4}')
if [[ ! $proceed_ram =~ ^[Yy]$ ]]; then 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}"
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." msg_error "Update cancelled by user."
exit exit
fi fi
@@ -67,55 +64,44 @@ function update_script() {
create_backup /opt/bichon/bichon.env 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" 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 restore_backup
if [ "$MIGRATE_V1" -eq 1 ]; then if [ "$MIGRATE_V2" -eq 1 ]; then
msg_info "Running Bichon v1 Data Migration (patience)" msg_info "Migrating storage from fjall to bichon-blob (patience)"
$STD apt install -y expect $STD apt install -y expect
# Menu: 0 Reset Password, 1 Migrate v0.3.7, 2 Migrate v1.x, 3 Exit
$STD expect <<'EOF' $STD expect <<'EOF'
set timeout -1 set timeout -1
spawn /opt/bichon/bichon-admin spawn /opt/bichon/bichon-admin
expect "*Select an operation*" expect "*Select an operation*"
send "\033\[B\r" send "\033\[B\033\[B\r"
expect "*--bichon-root-dir*" expect "*--bichon-root-dir*"
send "/opt/bichon-data\r" send "/opt/bichon-data\r"
expect "*--bichon-index-dir*"
send "\r"
expect "*--bichon-data-dir*" expect "*--bichon-data-dir*"
send "\r" send "\r"
expect "*Ready to migrate?*" expect "*batch size*"
send "y"
expect "*Enter batch size*"
send "1000\r" send "1000\r"
expect eof expect eof
catch wait catch wait
EOF EOF
$STD apt remove --purge expect -y $STD apt remove --purge expect -y
$STD apt autoremove -y $STD apt autoremove -y
msg_ok "Migration completed"
msg_info "Cleaning up legacy Bichon v0.x storage files" if [[ ! -d /opt/bichon-data/bichon-storage/blobs ]] ||
rm -rf /opt/bichon-data/envelope [[ "$(cat /opt/bichon-data/STORAGE_VERSION 2>/dev/null)" != "2" ]]; then
rm -rf /opt/bichon-data/eml msg_error "Storage migration did not complete - service left stopped, legacy data untouched."
rm -f /opt/bichon-data/mailbox.db msg_error "Run /opt/bichon/bichon-admin manually and select 'Migrate v1.x Storage to v2.x'."
rm -f /opt/bichon-data/meta.db exit
msg_ok "Cleanup completed" fi
msg_ok "Migrated storage to bichon-blob"
msg_info "Updating Bichon service for v1" msg_info "Removing legacy fjall files"
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 rm -rf /opt/bichon-data/bichon-storage/keyspaces
systemctl daemon-reload rm -f /opt/bichon-data/bichon-storage/0.jnl
msg_ok "Service updated" rm -f /opt/bichon-data/bichon-storage/lock
rm -f /opt/bichon-data/bichon-storage/version
msg_ok "Removed legacy fjall files"
fi fi
msg_info "Starting service" msg_info "Starting service"
+13 -1
View File
@@ -33,7 +33,19 @@ function update_script() {
systemctl stop cleanuparr systemctl stop cleanuparr
msg_ok "Stopped Service" msg_ok "Stopped Service"
create_backup /opt/cleanuparr/config 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
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip"
+3 -3
View File
@@ -37,9 +37,9 @@ function update_script() {
systemctl stop docmost systemctl stop docmost
msg_ok "Stopped Service" msg_ok "Stopped Service"
create_backup /opt/docmost/.env \ create_backup /opt/docmost/.env /opt/docmost/data
/opt/docmost/data
fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "docmost" "docmost/docmost" "tarball"
restore_backup restore_backup
+93
View File
@@ -0,0 +1,93 @@
#!/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}"
+6
View File
@@ -0,0 +1,6 @@
_______ __
/ ____(_)_______ ______________ __ __/ /
/ /_ / / ___/ _ \/ ___/ ___/ __ `/ | /| / / /
/ __/ / / / / __/ /__/ / / /_/ /| |/ |/ / /
/_/ /_/_/ \___/\___/_/ \__,_/ |__/|__/_/
+6
View File
@@ -0,0 +1,6 @@
____ _ ____ __
/ __ \____ ___ ____ (_) __ \____ __ __/ /____
/ / / / __ `__ \/ __ \/ / /_/ / __ \/ / / / __/ _ \
/ /_/ / / / / / / / / / / _, _/ /_/ / /_/ / /_/ __/
\____/_/ /_/ /_/_/ /_/_/_/ |_|\____/\__,_/\__/\___/
+6
View File
@@ -0,0 +1,6 @@
____ ____
/ __ \___ ____ _____ _/ __ \_________ _ __
/ /_/ / _ \/ __ `/ __ `/ /_/ / ___/ __ \| |/_/
/ ____/ __/ /_/ / /_/ / ____/ / / /_/ /> <
/_/ \___/\__, /\__,_/_/ /_/ \____/_/|_|
/____/
+2 -1
View File
@@ -110,7 +110,7 @@ EOF
msg_ok "Image-processing libraries up to date" msg_ok "Image-processing libraries up to date"
fi fi
RELEASE="v3.0.3" RELEASE="v3.1.0"
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 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 if [[ $(cat ~/.immich) > "2.5.1" ]]; then
msg_info "Enabling Maintenance Mode" msg_info "Enabling Maintenance Mode"
@@ -310,6 +310,7 @@ EOF
grep -rl /usr/src | xargs -n1 sed -i "s|\/usr/src|$INSTALL_DIR|g" 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" 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 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}" "$APP_DIR"/upload
ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$ML_DIR"/upload ln -s "${UPLOAD_DIR:-/opt/immich/upload}" "$ML_DIR"/upload
ln -s "$GEO_DIR" "$APP_DIR" ln -s "$GEO_DIR" "$APP_DIR"
+69
View File
@@ -0,0 +1,69 @@
#!/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}"
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}"
+64
View File
@@ -0,0 +1,64 @@
#!/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
View File
@@ -30,6 +30,12 @@ function update_script() {
exit exit
fi 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 NODE_VERSION="24" setup_nodejs
if check_for_gh_release "romm" "rommapp/romm"; then if check_for_gh_release "romm" "rommapp/romm"; then
@@ -44,6 +50,10 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "romm" "rommapp/romm" "tarball" "latest" "/opt/romm" 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 restore_backup
msg_info "Updating ROMM" msg_info "Updating ROMM"
+1
View File
@@ -22,6 +22,7 @@ chmod 775 /opt/bazarr /var/lib/bazarr/
sed -i.bak 's/--only-binary=Pillow//g' /opt/bazarr/requirements.txt sed -i.bak 's/--only-binary=Pillow//g' /opt/bazarr/requirements.txt
$STD uv venv --clear /opt/bazarr/venv --python 3.12 $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 -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_ok "Installed Bazarr"
msg_info "Creating Service" msg_info "Creating Service"
+1 -1
View File
@@ -60,7 +60,7 @@ LimitNOFILE=65536
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
systemctl enable -q --now bichon systemctl enable -q --now bichon
msg_info "Created Service" msg_ok "Created Service"
motd_ssh motd_ssh
customize customize
+3 -1
View File
@@ -16,6 +16,7 @@ update_os
fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip" fetch_and_deploy_gh_release "Cleanuparr" "Cleanuparr/Cleanuparr" "prebuild" "latest" "/opt/cleanuparr" "*linux-$(arch_resolve).zip"
msg_info "Creating Service" msg_info "Creating Service"
mkdir -p /etc/cleanuparr /var/log/cleanuparr
cat <<EOF >/etc/systemd/system/cleanuparr.service cat <<EOF >/etc/systemd/system/cleanuparr.service
[Unit] [Unit]
Description=Cleanuparr Daemon Description=Cleanuparr Daemon
@@ -29,7 +30,8 @@ ExecStart=/opt/cleanuparr/Cleanuparr
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
Environment="PORT=11011" Environment="PORT=11011"
Environment="CONFIG_DIR=/opt/cleanuparr/config" Environment="CLEANUPARR_CONFIG_PATH=/etc/cleanuparr"
Environment="CLEANUPARR_LOGS_PATH=/var/log/cleanuparr"
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
+230
View File
@@ -0,0 +1,230 @@
#!/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
+2 -1
View File
@@ -312,7 +312,7 @@ ML_DIR="${APP_DIR}/machine-learning"
GEO_DIR="${INSTALL_DIR}/geodata" GEO_DIR="${INSTALL_DIR}/geodata"
mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache} mkdir -p {"${APP_DIR}","${UPLOAD_DIR}","${GEO_DIR}","${INSTALL_DIR}"/cache}
fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.0.3" "$SRC_DIR" fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.1.0" "$SRC_DIR"
PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)" PNPM_VERSION="$(jq -r '.packageManager | split("@")[1] | split("+")[0]' ${SRC_DIR}/package.json)"
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs NODE_VERSION="24" NODE_MODULE="corepack" setup_nodejs
@@ -429,6 +429,7 @@ msg_info "Installing GeoNames data"
cd "$GEO_DIR" 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/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/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://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" 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 unzip -q cities500.zip
+7 -3
View File
@@ -19,12 +19,16 @@ $STD apt install -y \
git-core \ git-core \
mediainfo mediainfo
cat <<EOF >/etc/apt/sources.list.d/non-free.list cat <<EOF >/etc/apt/sources.list.d/non-free.sources
deb https://deb.debian.org/debian trixie main contrib non-free non-free-firmware 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
EOF EOF
$STD apt update $STD apt update
$STD apt install -y unrar $STD apt install -y unrar
rm /etc/apt/sources.list.d/non-free.list rm /etc/apt/sources.list.d/non-free.sources
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
msg_info "Installing Medusa" msg_info "Installing Medusa"
-6
View File
@@ -71,12 +71,6 @@ msg_ok "Created Service"
msg_info "Starting Service" msg_info "Starting Service"
systemctl enable -q --now nginx-ui systemctl enable -q --now nginx-ui
rm -rf /etc/nginx/sites-enabled/default 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" msg_ok "Started Service"
motd_ssh motd_ssh
+59
View File
@@ -0,0 +1,59 @@
#!/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="24" 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
+60
View File
@@ -0,0 +1,60 @@
#!/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
+2
View File
@@ -37,6 +37,8 @@ $STD apt install -y \
redis-server \ redis-server \
redis-tools \ redis-tools \
p7zip-full \ p7zip-full \
7zip-standalone \
libarchive-tools \
tzdata tzdata
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
+23 -2
View File
@@ -10,8 +10,29 @@ fi
# must write local failure artifacts instead of talking to the telemetry API # must write local failure artifacts instead of talking to the telemetry API
# (the host is the single telemetry reporter). # (the host is the single telemetry reporter).
export TELEMETRY_CONTEXT="container" export TELEMETRY_CONTEXT="container"
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func) # A freshly booted container may not have DNS up yet. `source <(curl ...)` hides
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func) # 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
load_functions load_functions
catch_errors catch_errors
+187 -27
View File
@@ -88,19 +88,38 @@ variables() {
fi fi
} }
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) # `source <(curl ...)` hides the download exit code, so a failed fetch would
# silently source an empty stream and leave the helpers undefined.
if command -v curl >/dev/null 2>&1; then _bootstrap_die() {
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func) if declare -f msg_error >/dev/null 2>&1; then
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func) msg_error "$1"
load_functions else
catch_errors echo "FATAL: $1" >&2
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 fi
exit 115
}
_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
load_functions
catch_errors
# ============================================================================== # ==============================================================================
# SECTION 2: PRE-FLIGHT CHECKS & SYSTEM VALIDATION # SECTION 2: PRE-FLIGHT CHECKS & SYSTEM VALIDATION
@@ -1111,6 +1130,7 @@ base_settings() {
APT_CACHER=${var_apt_cacher:-""} APT_CACHER=${var_apt_cacher:-""}
APT_CACHER_IP=${var_apt_cacher_ip:-""} APT_CACHER_IP=${var_apt_cacher_ip:-""}
INHERIT_HOST_CA="${var_inherit_host_ca:-no}"
# Runtime check: Verify APT cacher is reachable if configured # Runtime check: Verify APT cacher is reachable if configured
if [[ -n "$APT_CACHER_IP" && "$APT_CACHER" == "yes" ]]; then if [[ -n "$APT_CACHER_IP" && "$APT_CACHER" == "yes" ]]; then
@@ -1193,7 +1213,7 @@ load_vars_file() {
# Allowed var_* keys # Allowed var_* keys
local VAR_WHITELIST=( 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_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_inherit_host_ca var_keyctl
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu 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_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 var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
@@ -1390,6 +1410,12 @@ load_vars_file() {
continue continue
fi 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) var_container_storage | var_template_storage)
# Validate that the storage exists and is active on the current node # Validate that the storage exists and is active on the current node
local _storage_status local _storage_status
@@ -1429,7 +1455,7 @@ default_var_settings() {
# Allowed var_* keys (alphabetically sorted) # Allowed var_* keys (alphabetically sorted)
# Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique) # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
local VAR_WHITELIST=( 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_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_inherit_host_ca var_keyctl
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu 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_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_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage
@@ -1512,6 +1538,7 @@ var_ssh=no
# HTTP/HTTPS proxy (optional - for networks requiring a proxy) # HTTP/HTTPS proxy (optional - for networks requiring a proxy)
# var_http_proxy=http://proxy.local:8080 # var_http_proxy=http://proxy.local:8080
# var_http_no_proxy=localhost,127.0.0.1,.local # var_http_no_proxy=localhost,127.0.0.1,.local
# var_inherit_host_ca=no
# Features/Tags/verbosity # Features/Tags/verbosity
var_fuse=no var_fuse=no
@@ -1612,7 +1639,7 @@ get_app_defaults_path() {
if ! declare -p VAR_WHITELIST >/dev/null 2>&1; then 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) # Note: Removed var_ctid (can only exist once), var_ipv6_static (static IPs are unique)
declare -ag VAR_WHITELIST=( 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_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_inherit_host_ca var_keyctl
var_gateway var_hostname var_ipv6_method var_mac var_mknod var_mount_fs var_mtu 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_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 var_verbose var_version var_vlan var_ssh var_ssh_authorized_key var_container_storage var_template_storage var_searchdomain
@@ -1762,6 +1789,7 @@ _build_current_app_vars_tmp() {
_apt_cacher_ip="${APT_CACHER_IP:-}" _apt_cacher_ip="${APT_CACHER_IP:-}"
_http_proxy="${HTTP_PROXY:-${var_http_proxy:-}}" _http_proxy="${HTTP_PROXY:-${var_http_proxy:-}}"
_http_no_proxy="${HTTP_NO_PROXY:-${var_http_no_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}" _fuse="${ENABLE_FUSE:-no}"
_tun="${ENABLE_TUN:-no}" _tun="${ENABLE_TUN:-no}"
_gpu="${ENABLE_GPU:-no}" _gpu="${ENABLE_GPU:-no}"
@@ -1815,6 +1843,7 @@ _build_current_app_vars_tmp() {
[ -n "$_apt_cacher_ip" ] && echo "var_apt_cacher_ip=$(_sanitize_value "$_apt_cacher_ip")" [ -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_proxy" ] && echo "var_http_proxy=$(_sanitize_value "$_http_proxy")"
[ -n "$_http_no_proxy" ] && echo "var_http_no_proxy=$(_sanitize_value "$_http_no_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 "$_fuse" ] && echo "var_fuse=$(_sanitize_value "$_fuse")"
[ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")" [ -n "$_tun" ] && echo "var_tun=$(_sanitize_value "$_tun")"
@@ -1979,7 +2008,7 @@ advanced_settings() {
TAGS="community-script${var_tags:+;${var_tags}}" TAGS="community-script${var_tags:+;${var_tags}}"
fi fi
local STEP=1 local STEP=1
local MAX_STEP=30 local MAX_STEP=31
# Store values for back navigation - inherit from var_* app defaults # Store values for back navigation - inherit from var_* app defaults
local _ct_type="${var_unprivileged:-1}" local _ct_type="${var_unprivileged:-1}"
@@ -2001,6 +2030,7 @@ advanced_settings() {
local _apt_cacher_ip="${var_apt_cacher_ip:-}" local _apt_cacher_ip="${var_apt_cacher_ip:-}"
local _http_proxy="${var_http_proxy:-}" local _http_proxy="${var_http_proxy:-}"
local _http_no_proxy="${var_http_no_proxy:-}" local _http_no_proxy="${var_http_no_proxy:-}"
local _inherit_host_ca="${var_inherit_host_ca:-no}"
local _mtu="${var_mtu:-}" local _mtu="${var_mtu:-}"
local _sd="${var_searchdomain:-}" local _sd="${var_searchdomain:-}"
local _ns="${var_ns:-}" local _ns="${var_ns:-}"
@@ -2830,9 +2860,47 @@ advanced_settings() {
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 25: Container Timezone # STEP 25: Host CA Inheritance
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
25) 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" local tz_hint="$_ct_timezone"
[[ -z "$tz_hint" ]] && tz_hint="(empty - will use host timezone)" [[ -z "$tz_hint" ]] && tz_hint="(empty - will use host timezone)"
@@ -2855,9 +2923,9 @@ advanced_settings() {
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 26: Container Protection # STEP 27: Container Protection
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
26) 27)
local protect_default_flag="--defaultno" local protect_default_flag="--defaultno"
[[ "$_protect_ct" == "yes" || "$_protect_ct" == "1" ]] && protect_default_flag="" [[ "$_protect_ct" == "yes" || "$_protect_ct" == "1" ]] && protect_default_flag=""
@@ -2879,9 +2947,9 @@ advanced_settings() {
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 27: Device Node Creation (mknod) # STEP 28: Device Node Creation (mknod)
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
27) 28)
local mknod_default_flag="--defaultno" local mknod_default_flag="--defaultno"
[[ "$_enable_mknod" == "1" ]] && mknod_default_flag="" [[ "$_enable_mknod" == "1" ]] && mknod_default_flag=""
@@ -2903,9 +2971,9 @@ advanced_settings() {
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 28: Mount Filesystems # STEP 29: Mount Filesystems
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
28) 29)
local mount_hint="" local mount_hint=""
[[ -n "$_mount_fs" ]] && mount_hint="$_mount_fs" || mount_hint="(none)" [[ -n "$_mount_fs" ]] && mount_hint="$_mount_fs" || mount_hint="(none)"
@@ -2926,9 +2994,9 @@ advanced_settings() {
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 29: Optional host-side post-install hook (path on the Proxmox HOST) # STEP 30: Optional host-side post-install hook (path on the Proxmox HOST)
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
29) 30)
local _hook_prompt="Optional: absolute path to a *.sh file ON THE PROXMOX HOST. 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 It runs as root on the HOST (NOT in the LXC) after the container
@@ -2978,9 +3046,9 @@ Leave empty to skip."
;; ;;
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
# STEP 30: Verbose Mode & Confirmation # STEP 31: Verbose Mode & Confirmation
# ═══════════════════════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════════════════════
30) 31)
local verbose_default_flag="--defaultno" local verbose_default_flag="--defaultno"
[[ "$_verbose" == "yes" ]] && verbose_default_flag="" [[ "$_verbose" == "yes" ]] && verbose_default_flag=""
@@ -3009,6 +3077,7 @@ Leave empty to skip."
local apt_display="${_apt_cacher:-no}" local apt_display="${_apt_cacher:-no}"
[[ "$_apt_cacher" == "yes" && -n "$_apt_cacher_ip" ]] && apt_display="$_apt_cacher_ip" [[ "$_apt_cacher" == "yes" && -n "$_apt_cacher_ip" ]] && apt_display="$_apt_cacher_ip"
local http_proxy_display="${_http_proxy:-(none)}" 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_display="${_post_install:-(none)}"
local post_install_warn="" local post_install_warn=""
@@ -3039,6 +3108,7 @@ Advanced:
Timezone: $tz_display Timezone: $tz_display
APT Cacher: $apt_display APT Cacher: $apt_display
HTTP Proxy: $http_proxy_display HTTP Proxy: $http_proxy_display
Inherit Host CAs: $inherit_ca_display
Verbose: $_verbose Verbose: $_verbose
Post-Install Script: ${post_install_display}${post_install_warn}" Post-Install Script: ${post_install_display}${post_install_warn}"
@@ -3084,6 +3154,7 @@ Advanced:
APT_CACHER_IP="$_apt_cacher_ip" APT_CACHER_IP="$_apt_cacher_ip"
HTTP_PROXY="$_http_proxy" HTTP_PROXY="$_http_proxy"
HTTP_NO_PROXY="$_http_no_proxy" HTTP_NO_PROXY="$_http_no_proxy"
INHERIT_HOST_CA="$_inherit_host_ca"
VERBOSE="$_verbose" VERBOSE="$_verbose"
var_post_install="$_post_install" var_post_install="$_post_install"
@@ -3102,6 +3173,7 @@ Advanced:
var_sdn_vnet="$_sdn_vnet" var_sdn_vnet="$_sdn_vnet"
var_http_proxy="$_http_proxy" var_http_proxy="$_http_proxy"
var_http_no_proxy="$_http_no_proxy" var_http_no_proxy="$_http_no_proxy"
var_inherit_host_ca="$_inherit_host_ca"
# Format optional values # Format optional values
[[ -n "$_mtu" ]] && MTU=",mtu=$_mtu" || MTU="" [[ -n "$_mtu" ]] && MTU=",mtu=$_mtu" || MTU=""
@@ -4141,6 +4213,83 @@ EOF
msg_ok "Applied HTTP proxy in container" 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() # build_container()
# #
@@ -4770,6 +4919,7 @@ EOF
local install_exit_code=0 local install_exit_code=0
_apply_http_proxy_in_container _apply_http_proxy_in_container
_apply_host_ca_certs_in_container
# Continue with standard container setup # Continue with standard container setup
if [ "$var_os" == "alpine" ]; then if [ "$var_os" == "alpine" ]; then
@@ -5050,6 +5200,16 @@ EOF
# TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop) # TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop)
trap '' TSTP TTIN TTOU 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})" 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 # Copy install log from container BEFORE API call so get_error_text() can read it
+23 -2
View File
@@ -37,8 +37,29 @@ fi
# (the host is the single telemetry reporter). # (the host is the single telemetry reporter).
export TELEMETRY_CONTEXT="container" export TELEMETRY_CONTEXT="container"
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func) # A freshly booted container may not have DNS up yet. `source <(curl ...)` hides
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func) # 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
load_functions load_functions
catch_errors catch_errors
+78 -24
View File
@@ -2736,7 +2736,8 @@ get_latest_gl_tag() {
local repo_encoded local repo_encoded
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g') repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
local api_base="https://gitlab.com/api/v4/projects/${repo_encoded}/repository/tags" local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
local api_base="${gitlab_url}/api/v4/projects/${repo_encoded}/repository/tags"
local api_timeout="--connect-timeout 10 --max-time 60" local api_timeout="--connect-timeout 10 --max-time 60"
local header=() local header=()
@@ -2818,6 +2819,7 @@ get_latest_gl_tag() {
# Notes: # Notes:
# - Supports CLEAN_INSTALL=1 to wipe target before extracting # - Supports CLEAN_INSTALL=1 to wipe target before extracting
# - Supports GITLAB_TOKEN for private/rate-limited projects # - 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 # - For repos that only publish tags, not formal GitLab Releases
# (use fetch_and_deploy_gl_release for proper Releases with assets) # (use fetch_and_deploy_gl_release for proper Releases with assets)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -2861,8 +2863,9 @@ fetch_and_deploy_gl_tag() {
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g') repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
# GitLab source tarball URL (no release needed, works for any tag). # 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 version_safe="${resolved_tag//\//-}"
local tarball_url="https://gitlab.com/${repo}/-/archive/${resolved_tag}/${app_lc}-${version_safe}.tar.gz" local tarball_url="${gitlab_url}/${repo}/-/archive/${resolved_tag}/${app_lc}-${version_safe}.tar.gz"
local tmpdir local tmpdir
tmpdir=$(mktemp -d) || return 1 tmpdir=$(mktemp -d) || return 1
@@ -6947,6 +6950,60 @@ setup_mariadb_db() {
export MARIADB_DB_PASS 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. # Installs or updates MeiliSearch search engine.
# #
@@ -8195,22 +8252,17 @@ EOF
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
get_php_fpm_socket() { get_php_fpm_socket() {
local sock local sock
if [[ -n "${PHP_VERSION:-}" && -S "/run/php/php${PHP_VERSION}-fpm.sock" ]]; then if [[ -n "${PHP_VERSION:-}" && -S "/run/php/php${PHP_VERSION}-fpm.sock" ]]; then
echo "/run/php/php${PHP_VERSION}-fpm.sock" echo "/run/php/php${PHP_VERSION}-fpm.sock"
return 0 return 0
fi fi
sock=$(find /run/php -maxdepth 1 -name "php*-fpm.sock" -type s 2>/dev/null | sort -V | tail -1) sock=$(find /run/php -maxdepth 1 -name "php*-fpm.sock" -type s 2>/dev/null | sort -V | tail -1)
if [[ -z "$sock" ]]; then if [[ -z "$sock" ]]; then
msg_error "No active PHP-FPM socket found under /run/php" msg_error "No active PHP-FPM socket found under /run/php"
return 1 return 1
fi fi
echo "$sock" echo "$sock"
} }
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Enables an nginx site, validates the configuration and reloads the service. # Enables an nginx site, validates the configuration and reloads the service.
# #
@@ -8232,25 +8284,20 @@ get_php_fpm_socket() {
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
nginx_enable_site() { nginx_enable_site() {
local site="${1:-}" local site="${1:-}"
if [[ -z "$site" ]]; then if [[ -z "$site" ]]; then
msg_error "nginx_enable_site: no site name given" msg_error "nginx_enable_site: no site name given"
return 1 return 1
fi fi
if [[ ! -f "/etc/nginx/sites-available/${site}" ]]; then if [[ ! -f "/etc/nginx/sites-available/${site}" ]]; then
msg_error "nginx site config not found: /etc/nginx/sites-available/${site}" msg_error "nginx site config not found: /etc/nginx/sites-available/${site}"
return 1 return 1
fi fi
rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
ln -sf "/etc/nginx/sites-available/${site}" "/etc/nginx/sites-enabled/${site}" ln -sf "/etc/nginx/sites-available/${site}" "/etc/nginx/sites-enabled/${site}"
if ! $STD nginx -t; then if ! $STD nginx -t; then
msg_error "nginx configuration test failed for site '${site}'" msg_error "nginx configuration test failed for site '${site}'"
return 1 return 1
fi fi
$STD systemctl enable -q nginx $STD systemctl enable -q nginx
safe_service_restart nginx safe_service_restart nginx
} }
@@ -9447,11 +9494,12 @@ get_latest_gitlab_release() {
local temp_file local temp_file
temp_file=$(mktemp) temp_file=$(mktemp)
local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
local http_code local http_code
http_code=$(curl --connect-timeout 10 --max-time 30 -sSL \ http_code=$(curl --connect-timeout 10 --max-time 30 -sSL \
-w "%{http_code}" -o "$temp_file" \ -w "%{http_code}" -o "$temp_file" \
"${header[@]}" \ "${header[@]}" \
"https://gitlab.com/api/v4/projects/$repo_encoded/releases?per_page=1&order_by=released_at&sort=desc" 2>/dev/null) || true "${gitlab_url}/api/v4/projects/$repo_encoded/releases?per_page=1&order_by=released_at&sort=desc" 2>/dev/null) || true
if [[ "$http_code" != "200" ]]; then if [[ "$http_code" != "200" ]]; then
rm -f "$temp_file" rm -f "$temp_file"
@@ -9493,6 +9541,7 @@ get_latest_gitlab_release() {
# Notes: # Notes:
# - Requires `jq` (auto-installed if missing) # - Requires `jq` (auto-installed if missing)
# - Supports GITLAB_TOKEN env var for private/rate-limited repos # - 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 # - Does not modify anything, only checks version state
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
check_for_gl_release() { check_for_gl_release() {
@@ -9504,11 +9553,15 @@ check_for_gl_release() {
local app_lc="${app,,}" local app_lc="${app,,}"
local current_file="$HOME/.${app_lc}" 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}" msg_info "Checking for update: ${app}"
# DNS check # DNS check
if ! getent hosts gitlab.com >/dev/null 2>&1; then if ! getent hosts "$gitlab_hostname" >/dev/null 2>&1; then
msg_error "Network error: cannot resolve gitlab.com" msg_error "Network error: cannot resolve $gitlab_hostname"
return 6 return 6
fi fi
@@ -9531,7 +9584,7 @@ check_for_gl_release() {
local pinned_encoded="${pinned_version_in//\//%2F}" local pinned_encoded="${pinned_version_in//\//%2F}"
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \ http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \
"${header[@]}" \ "${header[@]}" \
"https://gitlab.com/api/v4/projects/$repo_encoded/releases/$pinned_encoded" 2>/dev/null) || true "${gitlab_url}/api/v4/projects/$repo_encoded/releases/$pinned_encoded" 2>/dev/null) || true
if [[ "$http_code" == "200" ]] && [[ -s "$gl_check_json" ]]; then if [[ "$http_code" == "200" ]] && [[ -s "$gl_check_json" ]]; then
releases_json="[$(<"$gl_check_json")]" releases_json="[$(<"$gl_check_json")]"
fi fi
@@ -9542,7 +9595,7 @@ check_for_gl_release() {
if [[ -z "$releases_json" ]]; then if [[ -z "$releases_json" ]]; then
http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \ http_code=$(curl -sSL --max-time 20 -w "%{http_code}" -o "$gl_check_json" \
"${header[@]}" \ "${header[@]}" \
"https://gitlab.com/api/v4/projects/$repo_encoded/releases?per_page=100&order_by=released_at&sort=desc" 2>/dev/null) || true "${gitlab_url}/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 if [[ "$http_code" == "200" ]] && [[ -s "$gl_check_json" ]]; then
releases_json=$(<"$gl_check_json") releases_json=$(<"$gl_check_json")
@@ -9566,7 +9619,7 @@ check_for_gl_release() {
return 22 return 22
elif [[ "$http_code" == "000" || -z "$http_code" ]]; then elif [[ "$http_code" == "000" || -z "$http_code" ]]; then
msg_error "GitLab API connection failed (no response)." msg_error "GitLab API connection failed (no response)."
msg_error "Check your network/DNS: curl -sSL https://gitlab.com/api/v4/version" msg_error "Check your network/DNS: curl -sSL ${gitlab_url}/api/v4/version"
rm -f "$gl_check_json" rm -f "$gl_check_json"
return 7 return 7
else else
@@ -9811,7 +9864,8 @@ fetch_and_deploy_gl_release() {
local repo_encoded local repo_encoded
repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g') repo_encoded=$(printf '%s' "$repo" | sed 's|/|%2F|g')
local api_base="https://gitlab.com/api/v4/projects/$repo_encoded/releases" local gitlab_url="${GITLAB_URL:-https://gitlab.com}"
local api_base="${gitlab_url}/api/v4/projects/$repo_encoded/releases"
local api_url local api_url
if [[ "$version" != "latest" ]]; then if [[ "$version" != "latest" ]]; then
api_url="$api_base/$version" api_url="$api_base/$version"
@@ -9860,7 +9914,7 @@ fetch_and_deploy_gl_release() {
msg_error " export GITLAB_TOKEN=\"glpat-your_token_here\"" msg_error " export GITLAB_TOKEN=\"glpat-your_token_here\""
elif [[ "$http_code" == "000" || -z "$http_code" ]]; then elif [[ "$http_code" == "000" || -z "$http_code" ]]; then
msg_error "GitLab API connection failed (no response)." msg_error "GitLab API connection failed (no response)."
msg_error "Check your network/DNS: curl -sSL https://gitlab.com/api/v4/version" msg_error "Check your network/DNS: curl -sSL ${gitlab_url}/api/v4/version"
else else
msg_error "Failed to fetch release metadata (HTTP $http_code)" msg_error "Failed to fetch release metadata (HTTP $http_code)"
fi fi
@@ -9915,7 +9969,7 @@ fetch_and_deploy_gl_release() {
### Tarball Mode ### ### Tarball Mode ###
if [[ "$mode" == "tarball" || "$mode" == "source" ]]; then if [[ "$mode" == "tarball" || "$mode" == "source" ]]; then
local direct_tarball_url="https://gitlab.com/$repo/-/archive/$tag_name/${app_lc}-${version_safe}.tar.gz" local direct_tarball_url="${gitlab_url}/$repo/-/archive/$tag_name/${app_lc}-${version_safe}.tar.gz"
filename="${app_lc}-${version_safe}.tar.gz" filename="${app_lc}-${version_safe}.tar.gz"
_download_source_tarball "$direct_tarball_url" "$tmpdir/$filename" "${header[@]}" || { _download_source_tarball "$direct_tarball_url" "$tmpdir/$filename" "${header[@]}" || {
@@ -9963,7 +10017,7 @@ fetch_and_deploy_gl_release() {
if [[ -z "$url_match" ]]; then if [[ -z "$url_match" ]]; then
local fallback_json local fallback_json
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "binary" "$asset_pattern" "$tag_name"); then if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "binary" "$asset_pattern" "$tag_name"); then
json="$fallback_json" json="$fallback_json"
tag_name=$(echo "$json" | jq -r '.tag_name // empty') tag_name=$(echo "$json" | jq -r '.tag_name // empty')
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name" [[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
@@ -10035,7 +10089,7 @@ fetch_and_deploy_gl_release() {
if [[ -z "$asset_url" ]]; then if [[ -z "$asset_url" ]]; then
local fallback_json local fallback_json
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "prebuild" "$pattern" "$tag_name"); then if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "prebuild" "$pattern" "$tag_name"); then
json="$fallback_json" json="$fallback_json"
tag_name=$(echo "$json" | jq -r '.tag_name // empty') tag_name=$(echo "$json" | jq -r '.tag_name // empty')
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name" [[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
@@ -10088,7 +10142,7 @@ fetch_and_deploy_gl_release() {
if [[ -z "$asset_url" ]]; then if [[ -z "$asset_url" ]]; then
local fallback_json local fallback_json
if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "https://gitlab.com" "singlefile" "$pattern" "$tag_name"); then if fallback_json=$(_gl_scan_older_releases "$repo" "$repo_encoded" "$gitlab_url" "singlefile" "$pattern" "$tag_name"); then
json="$fallback_json" json="$fallback_json"
tag_name=$(echo "$json" | jq -r '.tag_name // empty') tag_name=$(echo "$json" | jq -r '.tag_name // empty')
[[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name" [[ "$tag_name" =~ ^v[0-9] ]] && version="${tag_name:1}" || version="$tag_name"
+29 -23
View File
@@ -6,6 +6,19 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://netbird.io/ | Github: https://github.com/netbirdio/netbird # Source: https://netbird.io/ | Github: https://github.com/netbirdio/netbird
APP="add-netbird-lxc"
APP_TYPE="addon"
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 "add-netbird-lxc" "addon"
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
function header_info { function header_info {
clear clear
cat <<"EOF" cat <<"EOF"
@@ -17,28 +30,22 @@ function header_info {
EOF EOF
} }
header_info
set -e
# Telemetry # Initialize all core functions (colors, formatting, icons, STD mode)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true load_functions
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "addon"
header_info
while true; do while true; do
read -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn read -r -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn
case $yn in case $yn in
[Yy]*) break ;; [Yy]*) break ;;
[Nn]*) exit ;; [Nn]*) exit 0 ;;
*) echo "Please answer yes or no." ;; *) echo "Please answer yes or no." ;;
esac esac
done done
header_info header_info
echo "Loading..." msg_info "Loading container list..."
function msg() {
local TEXT="$1"
echo -e "$TEXT"
}
NODE=$(hostname) NODE=$(hostname)
MSG_MAX_LENGTH=0 MSG_MAX_LENGTH=0
@@ -61,28 +68,28 @@ done
LXC_STATUS=$(pct status "$CTID" | awk '{print $2}') LXC_STATUS=$(pct status "$CTID" | awk '{print $2}')
if [[ "$LXC_STATUS" != "running" ]]; then if [[ "$LXC_STATUS" != "running" ]]; then
msg "\e[1;33m The container $CTID is not running. Starting it now...\e[0m" msg_info "Container $CTID is not running. Starting it now..."
pct start "$CTID" pct start "$CTID"
while [[ "$(pct status "$CTID" | awk '{print $2}')" != "running" ]]; do while [[ "$(pct status "$CTID" | awk '{print $2}')" != "running" ]]; do
msg "\e[1;33m Waiting for the container to start...\e[0m" msg_info "Waiting for the container to start..."
sleep 2 sleep 2
done done
msg "\e[1;32m Container $CTID is now running.\e[0m" msg_ok "Container $CTID is now running."
fi fi
DISTRO=$(pct exec "$CTID" -- cat /etc/os-release | grep -w "ID" | cut -d'=' -f2 | tr -d '"') DISTRO=$(pct exec "$CTID" -- cat /etc/os-release | grep -w "ID" | cut -d'=' -f2 | tr -d '"')
if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then
msg "\e[1;31m Error: This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting...\e[0m" msg_error "This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting..."
exit 238 exit 238
fi fi
CTID_CONFIG_PATH=/etc/pve/lxc/${CTID}.conf CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
cat <<EOF >>$CTID_CONFIG_PATH cat <<EOF >>"$CTID_CONFIG_PATH"
lxc.cgroup2.devices.allow: c 10:200 rwm lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
EOF EOF
header_info header_info
msg "Installing NetBird..." msg_info "Installing NetBird"
pct exec "$CTID" -- bash -c ' pct exec "$CTID" -- bash -c '
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
apt-get update -qq apt-get update -qq
@@ -103,6 +110,5 @@ OVERRIDE
systemctl daemon-reload systemctl daemon-reload
fi fi
' '
msg "\e[1;32m ✔ Installed NetBird.\e[0m" msg_ok "Installed NetBird."
sleep 2 echo -e "${YW}Reboot ${CTID} LXC${CL} to apply the changes, then run 'netbird up' in the LXC console"
msg "\e[1;31m Reboot ${CTID} LXC to apply the changes, then run netbird up in the LXC console\e[0m"
+14 -9
View File
@@ -5,8 +5,18 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://tailscale.com/ | Github: https://github.com/tailscale/tailscale # Source: https://tailscale.com/ | Github: https://github.com/tailscale/tailscale
APP="add-tailscale-lxc"
APP_TYPE="addon"
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 "add-tailscale-lxc" "addon"
# Enable error handling
set -Eeuo pipefail set -Eeuo pipefail
trap 'echo -e "\n[ERROR] in line $LINENO: exit code $?"' ERR trap 'error_handler' ERR
function header_info() { function header_info() {
clear clear
@@ -20,13 +30,8 @@ function header_info() {
EOF EOF
} }
function msg_info() { echo -e " \e[1;36m➤\e[0m $1"; } # Initialize all core functions (colors, formatting, icons, STD mode)
function msg_ok() { echo -e " \e[1;32m✔\e[0m $1"; } load_functions
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"
header_info header_info
@@ -168,4 +173,4 @@ TAGS="${TAGS:+$TAGS; }tailscale"
pct set "$CTID" -tags "$TAGS" pct set "$CTID" -tags "$TAGS"
msg_ok "Tailscale installed on CT $CTID" msg_ok "Tailscale installed on CT $CTID"
msg_info "Reboot the container, then run 'tailscale up' inside the container to activate." echo -e "${YW}Reboot the container${CL}, then run 'tailscale up' inside the container to activate."
+10 -38
View File
@@ -10,8 +10,8 @@ if ! command -v curl &>/dev/null; then
if [[ -f "/etc/alpine-release" ]]; then if [[ -f "/etc/alpine-release" ]]; then
apk -U add curl >/dev/null 2>&1 apk -U add curl >/dev/null 2>&1
else else
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt install -y curl >/dev/null 2>&1
fi fi
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/core.func)
@@ -36,28 +36,6 @@ DEFAULT_PORT=8080
# Initialize all core functions (colors, formatting, icons, STD mode) # Initialize all core functions (colors, formatting, icons, STD mode)
load_functions 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 # OS DETECTION
# ============================================================================== # ==============================================================================
@@ -114,16 +92,12 @@ function update() {
fi fi
msg_ok "Stopped service" msg_ok "Stopped service"
msg_info "Backing up configuration" BACKUP_DIR="/opt/adguardhome-sync_backup"
cp "$CONFIG_PATH" /tmp/adguardhome-sync.yaml.bak 2>/dev/null || true create_backup "$CONFIG_PATH"
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_amd64.tar.gz" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
msg_info "Restoring configuration" restore_backup
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" msg_info "Starting service"
if [[ "$OS" == "Alpine" ]]; then if [[ "$OS" == "Alpine" ]]; then
@@ -141,10 +115,7 @@ function update() {
# INSTALL # INSTALL
# ============================================================================== # ==============================================================================
function install() { function install() {
local ip fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
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 # Gather configuration from user
echo "" echo ""
@@ -293,7 +264,7 @@ UPDATEEOF
echo "" echo ""
msg_ok "${APP} installed successfully" 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}" msg_ok "Config: ${BL}${CONFIG_PATH}${CL}"
echo "" echo ""
msg_warn "Edit the config file to add your AdGuardHome instances!" msg_warn "Edit the config file to add your AdGuardHome instances!"
@@ -319,7 +290,8 @@ fi
header_info header_info
IP=$(get_ip) get_lxc_ip
IP="$LOCAL_IP"
# Check if already installed # Check if already installed
if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/adguardhome-sync" ]]; then if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/adguardhome-sync" ]]; then
+61 -57
View File
@@ -1,8 +1,17 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck # Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) # Author: tteck (tteckster)
# License: MIT # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
APP="all-templates"
APP_TYPE="addon"
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 "all-templates" "addon"
function header_info { function header_info {
clear clear
@@ -15,37 +24,17 @@ function header_info {
EOF EOF
} }
set -eEuo pipefail # Enable error handling; destroy any partially-created container before reporting the error
shopt -s expand_aliases set -Eeuo pipefail
alias die='EXIT=$? LINE=$LINENO error_exit' function _cleanup_on_error() {
trap die ERR local ec=$? cmd="$BASH_COMMAND"
function error_exit() { [[ -n "${CTID:-}" ]] && cleanup_ctid
trap - ERR error_handler "$ec" "$cmd"
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"
} }
trap '_cleanup_on_error' ERR
# Telemetry # Initialize all core functions (colors, formatting, icons, STD mode)
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true load_functions
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "addon"
function validate_container_id() { function validate_container_id() {
local ctid="$1" local ctid="$1"
@@ -84,7 +73,7 @@ if systemctl is-active -q ping-instances.service; then
systemctl stop ping-instances.service systemctl stop ping-instances.service
fi fi
header_info header_info
echo "Loading..." msg_info "Loading"
pveam update >/dev/null 2>&1 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 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=() TEMPLATE_MENU=()
@@ -97,8 +86,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 '"') 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" ] && { [ -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 whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Template LXC Selected" --msgbox "It appears that no Template LXC container was selected" 10 68
msg "Done" echo "Done"
exit exit 0
} }
# Setup script environment # Setup script environment
@@ -108,9 +97,9 @@ PASS="$(openssl rand -base64 8)"
# Get valid Container ID # Get valid Container ID
CTID=$(pvesh get /cluster/nextid) CTID=$(pvesh get /cluster/nextid)
if ! validate_container_id "$CTID"; then if ! validate_container_id "$CTID"; then
warn "Container ID $CTID is already in use." msg_warn "Container ID $CTID is already in use."
CTID=$(get_valid_container_id "$CTID") CTID=$(get_valid_container_id "$CTID")
info "Using next available ID: $CTID" msg_info "Using next available ID: $CTID"
fi fi
PCT_OPTIONS=" PCT_OPTIONS="
@@ -142,7 +131,10 @@ function select_storage() {
CONTENT='vztmpl' CONTENT='vztmpl'
CONTENT_LABEL='Container template' CONTENT_LABEL='Container template'
;; ;;
*) false || die "Invalid storage class." ;; *)
msg_error "Invalid storage class."
exit 1
;;
esac esac
# Query all storage locations # Query all storage locations
@@ -161,8 +153,9 @@ function select_storage() {
# Select storage location # Select storage location
if [ $((${#MENU[@]} / 3)) -eq 0 ]; then if [ $((${#MENU[@]} / 3)) -eq 0 ]; then
warn "'$CONTENT_LABEL' needs to be selected for at least one storage location." msg_warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
die "Unable to detect valid storage location." msg_error "Unable to detect valid storage location."
exit 1
elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then
printf ${MENU[0]} printf ${MENU[0]}
else else
@@ -171,7 +164,10 @@ function select_storage() {
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \ 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" \ "Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\n\n" \
16 $(($MSG_MAX_LENGTH + 23)) 6 \ 16 $(($MSG_MAX_LENGTH + 23)) 6 \
"${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted." "${MENU[@]}" 3>&1 1>&2 2>&3) || {
msg_error "Menu aborted."
exit 1
}
done done
printf $STORAGE printf $STORAGE
fi fi
@@ -179,35 +175,43 @@ function select_storage() {
header_info header_info
# Get template storage # Get template storage
TEMPLATE_STORAGE=$(select_storage template) TEMPLATE_STORAGE=$(select_storage template)
info "Using '$TEMPLATE_STORAGE' for template storage." msg_info "Using '$TEMPLATE_STORAGE' for template storage."
# Get container storage # Get container storage
CONTAINER_STORAGE=$(select_storage container) CONTAINER_STORAGE=$(select_storage container)
info "Using '$CONTAINER_STORAGE' for container storage." msg_info "Using '$CONTAINER_STORAGE' for container storage."
# Download template # Download template
msg "Downloading LXC template (Patience)..." msg_info "Downloading LXC template (Patience)"
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || die "A problem occured while downloading the LXC template." pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || {
msg_error "A problem occured while downloading the LXC template."
exit 1
}
msg_ok "Downloaded LXC template"
# Create variable for 'pct' options # Create variable for 'pct' options
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_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 # Create LXC
msg "Creating LXC container..." msg_info "Creating LXC container"
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null || pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} "${PCT_OPTIONS[@]}" >/dev/null || {
die "A problem occured while trying to create container." msg_error "A problem occured while trying to create container."
exit 1
}
msg_ok "Created LXC container"
# Save password # Save password
echo "$NAME password: ${PASS}" >>~/$NAME.creds # file is located in the Proxmox root directory echo "$NAME password: ${PASS}" >>~/$NAME.creds # file is located in the Proxmox root directory
# Start container # Start container
msg "Starting LXC Container..." msg_info "Starting LXC Container"
pct start "$CTID" pct start "$CTID"
sleep 5 sleep 5
msg_ok "Started LXC Container"
# Get container IP # Get container IP
set +eEuo pipefail set +Eeuo pipefail
max_attempts=5 max_attempts=5
attempt=1 attempt=1
IP="" IP=""
@@ -216,18 +220,18 @@ while [[ $attempt -le $max_attempts ]]; do
if [[ -n $IP ]]; then if [[ -n $IP ]]; then
break break
else else
warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..." msg_warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
sleep 5 sleep 5
((attempt++)) ((attempt++))
fi fi
done done
if [[ -z $IP ]]; then if [[ -z $IP ]]; then
warn "Maximum number of attempts reached. IP address not found." msg_warn "Maximum number of attempts reached. IP address not found."
IP="NOT FOUND" IP="NOT FOUND"
fi fi
set -eEuo pipefail set -Eeuo pipefail
# Start Proxmox VE Monitor-All if available # Start Proxmox VE Monitor-All if available
if [[ -f /etc/systemd/system/ping-instances.service ]]; then if [[ -f /etc/systemd/system/ping-instances.service ]]; then
systemctl start ping-instances.service systemctl start ping-instances.service
@@ -236,10 +240,10 @@ fi
# Success message # Success message
header_info header_info
echo echo
info "LXC container '$CTID' was successfully created, and its IP address is ${IP}." msg_ok "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
echo echo
info "Proceed to the LXC console to complete the setup." echo -e "${YW}Proceed to the LXC console to complete the setup.${CL}"
echo echo
info "login: root" echo -e "${YW}login: root${CL}"
info "password: $PASS" echo -e "${YW}password: $PASS${CL}"
echo echo
+2 -17
View File
@@ -6,8 +6,8 @@
# Source: https://github.com/getarcaneapp/arcane # Source: https://github.com/getarcaneapp/arcane
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt 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/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/tools.func)
@@ -32,21 +32,6 @@ DEFAULT_PORT=3552
# Initialize all core functions (colors, formatting, icons, STD mode) # Initialize all core functions (colors, formatting, icons, STD mode)
load_functions load_functions
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
___ ____ _________ _ ________
/ | / __ \/ ____/ | / | / / ____/
/ /| | / /_/ / / / /| | / |/ / __/
/ ___ |/ _, _/ /___/ ___ |/ /| / /___
/_/ |_/_/ |_|\____/_/ |_/_/ |_/_____/
EOF
}
# ============================================================================== # ==============================================================================
# UNINSTALL # UNINSTALL
# ============================================================================== # ==============================================================================
+114 -76
View File
@@ -5,100 +5,79 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://coder.com/ | Github: https://github.com/coder/code-server # Source: https://coder.com/ | Github: https://github.com/coder/code-server
function header_info { source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
cat <<"EOF" 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")
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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "coder-code-server" "addon"
set -o errexit # Enable error handling
set -o errtrace set -Eeuo pipefail
set -o nounset trap 'error_handler' ERR
set -o pipefail
shopt -s expand_aliases APP="Coder Code Server"
alias die='EXIT=$? LINE=$LINENO error_exit' APP_TYPE="addon"
trap die ERR
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
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"
}
clear
header_info header_info
ensure_usr_local_bin_persist
get_lxc_ip
IP="$LOCAL_IP"
if command -v pveversion >/dev/null 2>&1; then if command -v pveversion >/dev/null 2>&1; then
echo -e "⚠️ Can't Install on Proxmox " msg_error "Can't Install on Proxmox"
exit exit 1
fi fi
if [ -e /etc/alpine-release ]; then if [ -e /etc/alpine-release ]; then
echo -e "⚠️ Can't Install on Alpine" msg_error "Can't Install on Alpine"
exit 1
fi
# ==============================================================================
# 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"
}
# ==============================================================================
# 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!"
exit exit
fi 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" msg_info "Installing Dependencies"
apt-get update &>/dev/null $STD apt update
apt-get install -y curl &>/dev/null $STD apt install -y \
apt-get install -y git &>/dev/null curl \
git
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
VERSION=$(curl -fsSL https://api.github.com/repos/coder/code-server/releases/latest | msg_info "Installing ${APP}"
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" config_path="${HOME}/.config/code-server/config.yaml"
preexisting_config=false preexisting_config=false
if [ -f "$config_path" ]; then if [ -f "$config_path" ]; then
preexisting_config=true preexisting_config=true
fi fi
curl -fOL https://github.com/coder/code-server/releases/download/v"$VERSION"/code-server_"${VERSION}"_amd64.deb &>/dev/null fetch_and_deploy_gh_release "coder-code-server" "coder/code-server" "binary" "latest" "/opt/coder-code-server" "code-server_*_$(arch_resolve).deb"
dpkg -i code-server_"${VERSION}"_amd64.deb &>/dev/null
rm -rf code-server_"${VERSION}"_amd64.deb
mkdir -p "${HOME}/.config/code-server/" mkdir -p "${HOME}/.config/code-server/"
if [ "$preexisting_config" = false ]; then if [ "$preexisting_config" = false ]; then
@@ -112,9 +91,68 @@ fi
systemctl enable -q --now code-server@"$USER" systemctl enable -q --now code-server@"$USER"
systemctl restart code-server@"$USER" systemctl restart code-server@"$USER"
if ! systemctl is-active --quiet code-server@"$USER"; then if ! systemctl is-active --quiet code-server@"$USER"; then
error_exit "code-server service failed to start." msg_error "code-server service failed to start."
exit 1
fi fi
msg_ok "Installed Code-Server v${VERSION} on $hostname" 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)"
echo -e "${APP} should be reachable by going to the following URL. echo -e "${APP} should be reachable by going to the following URL.
${BL}http://$IP:8680${CL} \n" ${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
+13 -20
View File
@@ -7,8 +7,8 @@
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt 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/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/tools.func)
@@ -45,28 +45,13 @@ if [[ -f "/etc/alpine-release" ]]; then
SERVICE_PATH="/etc/init.d/copyparty" SERVICE_PATH="/etc/init.d/copyparty"
elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
OS="Debian" OS="Debian"
PKG_MANAGER="apt-get install -y" PKG_MANAGER="apt install -y"
SERVICE_PATH="/etc/systemd/system/copyparty.service" SERVICE_PATH="/etc/systemd/system/copyparty.service"
else else
msg_error "Unsupported OS detected. Exiting." msg_error "Unsupported OS detected. Exiting."
exit 238 exit 238
fi fi
# ==============================================================================
# HEADER
# ==============================================================================
function header_info() {
clear
cat <<"EOF"
______ ____ __
/ ____/___ ____ __ __/ __ \____ ______/ /___ __
/ / / __ \/ __ \/ / / / /_/ / __ `/ ___/ __/ / / /
/ /___/ /_/ / /_/ / /_/ / ____/ /_/ / / / /_/ /_/ /
\____/\____/ .___/\__, /_/ \__,_/_/ \__/\__, /
/_/ /____/ /____/
EOF
}
# ============================================================================== # ==============================================================================
# HELPER FUNCTIONS # HELPER FUNCTIONS
# ============================================================================== # ==============================================================================
@@ -173,9 +158,17 @@ function install() {
msg_info "Installing dependencies" msg_info "Installing dependencies"
if [[ "$OS" == "Debian" ]]; then if [[ "$OS" == "Debian" ]]; then
$STD $PKG_MANAGER python3 python3-pil ffmpeg curl $STD $PKG_MANAGER \
python3 \
python3-pil \
ffmpeg \
curl
else else
$STD $PKG_MANAGER python3 py3-pillow ffmpeg curl $STD $PKG_MANAGER \
python3 \
py3-pillow \
ffmpeg \
curl
fi fi
msg_ok "Dependencies installed (with thumbnail support)" msg_ok "Dependencies installed (with thumbnail support)"
+5 -24
View File
@@ -7,8 +7,8 @@
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt 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/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/tools.func)
@@ -31,21 +31,6 @@ CONFIG_PATH="/opt/cronmaster/.env"
SERVICE_PATH="/etc/systemd/system/cronmaster.service" SERVICE_PATH="/etc/systemd/system/cronmaster.service"
DEFAULT_PORT=3000 DEFAULT_PORT=3000
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
______ __ ___ __
/ ____/________ ____ / |/ /___ ______/ /____ _____
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/
EOF
}
# ============================================================================== # ==============================================================================
# OS DETECTION # OS DETECTION
# ============================================================================== # ==============================================================================
@@ -77,16 +62,12 @@ function update() {
systemctl stop cronmaster.service &>/dev/null || true systemctl stop cronmaster.service &>/dev/null || true
msg_ok "Stopped service" msg_ok "Stopped service"
msg_info "Backing up configuration" BACKUP_DIR="/opt/cronmaster_backup"
cp "$CONFIG_PATH" /tmp/cronmaster.env.bak 2>/dev/null || true create_backup "$CONFIG_PATH"
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
msg_info "Restoring configuration" restore_backup
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" msg_info "Starting service"
systemctl start cronmaster systemctl start cronmaster
+26 -61
View File
@@ -5,89 +5,54 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.crowdsec.net/ | Github: https://github.com/crowdsecurity/crowdsec # 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="CrowdSec"
hostname="$(hostname)" APP_TYPE="addon"
# Telemetry 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "crowdsec" "addon"
set -o errexit # Enable error handling
set -o errtrace set -Eeuo pipefail
set -o nounset trap 'error_handler' ERR
set -o pipefail
shopt -s expand_aliases # Initialize all core functions (colors, formatting, icons, STD mode)
alias die='EXIT=$? LINE=$LINENO error_exit' load_functions
trap die ERR
header_info
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 if command -v pveversion >/dev/null 2>&1; then
echo -e "⚠️ Can't Install on Proxmox " msg_error "Can't Install on Proxmox"
exit exit 1
fi fi
while true; do while true; do
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
read -r yn
case $yn in case $yn in
[Yy]*) break ;; [Yy]*) break ;;
[Nn]*) exit ;; [Nn]*) exit ;;
*) echo "Please answer yes or no." ;; *) echo "Please answer yes or no." ;;
esac esac
done 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" msg_info "Setting up ${APP} Repository"
apt-get update &>/dev/null $STD apt update
apt-get install -y curl &>/dev/null $STD apt install -y \
apt-get install -y gnupg &>/dev/null curl \
curl -fsSL "https://install.crowdsec.net" | bash &>/dev/null gnupg
$STD bash -c "curl -fsSL https://install.crowdsec.net | bash"
msg_ok "Setup ${APP} Repository" msg_ok "Setup ${APP} Repository"
msg_info "Installing ${APP}" msg_info "Installing ${APP}"
apt-get update &>/dev/null $STD apt update
apt-get install -y crowdsec &>/dev/null $STD apt install -y crowdsec
msg_ok "Installed ${APP} on $hostname" msg_ok "Installed ${APP}"
msg_info "Installing ${APP} Common Bouncer" msg_info "Installing ${APP} Common Bouncer"
apt-get install -y crowdsec-firewall-bouncer-iptables &>/dev/null $STD apt install -y crowdsec-firewall-bouncer-iptables
msg_ok "Installed ${APP} Common Bouncer" msg_ok "Installed ${APP} Common Bouncer"
msg_ok "Completed successfully!\n" msg_ok "Completed successfully!\n"
+54 -72
View File
@@ -5,55 +5,41 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/filebrowserspace/quantum # 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="FileBrowser Quantum"
APP_TYPE="addon"
INSTALL_PATH="/usr/local/bin/filebrowser" INSTALL_PATH="/usr/local/bin/filebrowser"
CONFIG_PATH="/usr/local/community-scripts/fq-config.yaml" CONFIG_PATH="/usr/local/community-scripts/fq-config.yaml"
DEFAULT_PORT=8080 DEFAULT_PORT=8080
SRC_DIR="/" SRC_DIR="/"
TMP_BIN="/tmp/filebrowser.$$"
# Telemetry 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser-quantum" "addon"
# Get primary IP # Enable error handling
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}') set -Eeuo pipefail
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1) trap 'error_handler' ERR
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
[[ -z "$IP" ]] && IP="127.0.0.1" # Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
header_info
get_lxc_ip
IP="$LOCAL_IP"
# Proxmox Host Warning # Proxmox Host Warning
if [[ -d "/etc/pve" ]]; then if [[ -d "/etc/pve" ]]; then
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}" msg_warn "Running this addon directly on the Proxmox host is not recommended!"
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}" msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}" msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}" msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
echo "" echo ""
echo -n "Continue anyway on the Proxmox host? (y/N): " echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
read -r host_confirm read -r host_confirm
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
echo -e "${YW}Aborted.${CL}" msg_error "Aborted."
exit 0 exit 0
fi fi
fi fi
@@ -66,18 +52,12 @@ if [[ -f "/etc/alpine-release" ]]; then
elif [[ -f "/etc/debian_version" ]]; then elif [[ -f "/etc/debian_version" ]]; then
OS="Debian" OS="Debian"
SERVICE_PATH="/etc/systemd/system/filebrowser.service" SERVICE_PATH="/etc/systemd/system/filebrowser.service"
PKG_MANAGER="apt-get install -y" PKG_MANAGER="apt install -y"
else else
echo -e "${CROSS} Unsupported OS detected. Exiting." msg_error "Unsupported OS detected. Exiting."
exit 238 exit 238
fi 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 # Detect legacy FileBrowser installation
LEGACY_DB="/usr/local/community-scripts/filebrowser.db" LEGACY_DB="/usr/local/community-scripts/filebrowser.db"
LEGACY_BIN="/usr/local/bin/filebrowser" LEGACY_BIN="/usr/local/bin/filebrowser"
@@ -85,80 +65,82 @@ LEGACY_SERVICE_DEB="/etc/systemd/system/filebrowser.service"
LEGACY_SERVICE_ALP="/etc/init.d/filebrowser" LEGACY_SERVICE_ALP="/etc/init.d/filebrowser"
if [[ -f "$LEGACY_DB" || -f "$LEGACY_BIN" && ! -f "$CONFIG_PATH" ]]; then if [[ -f "$LEGACY_DB" || -f "$LEGACY_BIN" && ! -f "$CONFIG_PATH" ]]; then
echo -e "${YW}⚠️ Detected legacy FileBrowser installation.${CL}" msg_warn "Detected legacy FileBrowser installation."
echo -n "Uninstall legacy FileBrowser and continue with Quantum install? (y/n): " echo -n "${TAB}Uninstall legacy FileBrowser and continue with Quantum install? (y/n): "
read -r remove_legacy read -r remove_legacy
if [[ "${remove_legacy,,}" =~ ^(y|yes)$ ]]; then if [[ "${remove_legacy,,}" =~ ^(y|yes)$ ]]; then
msg_info "Uninstalling legacy FileBrowser" msg_info "Uninstalling legacy FileBrowser"
if [[ -f "$LEGACY_SERVICE_DEB" ]]; then if [[ -f "$LEGACY_SERVICE_DEB" ]]; then
systemctl disable --now filebrowser.service &>/dev/null systemctl disable --now filebrowser.service &>/dev/null || true
rm -f "$LEGACY_SERVICE_DEB" rm -f "$LEGACY_SERVICE_DEB"
elif [[ -f "$LEGACY_SERVICE_ALP" ]]; then elif [[ -f "$LEGACY_SERVICE_ALP" ]]; then
rc-service filebrowser stop &>/dev/null rc-service filebrowser stop &>/dev/null || true
rc-update del filebrowser &>/dev/null rc-update del filebrowser &>/dev/null || true
rm -f "$LEGACY_SERVICE_ALP" rm -f "$LEGACY_SERVICE_ALP"
fi fi
rm -f "$LEGACY_BIN" "$LEGACY_DB" rm -f "$LEGACY_BIN" "$LEGACY_DB"
msg_ok "Legacy FileBrowser removed" msg_ok "Legacy FileBrowser removed"
else else
echo -e "${YW}Installation aborted by user.${CL}" msg_error "Installation aborted by user."
exit 0 exit 0
fi fi
fi fi
# Existing installation # Existing installation
if [[ -f "$INSTALL_PATH" ]]; then if [[ -f "$INSTALL_PATH" ]]; then
echo -e "${YW}⚠️ ${APP} is already installed.${CL}" msg_warn "${APP} is already installed."
echo -n "Uninstall ${APP}? (y/N): " echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Uninstalling ${APP}" msg_info "Uninstalling ${APP}"
if [[ "$OS" == "Debian" ]]; then if [[ "$OS" == "Debian" ]]; then
systemctl disable --now filebrowser.service &>/dev/null systemctl disable --now filebrowser.service &>/dev/null || true
rm -f "$SERVICE_PATH" rm -f "$SERVICE_PATH"
else else
rc-service filebrowser stop &>/dev/null rc-service filebrowser stop &>/dev/null || true
rc-update del filebrowser &>/dev/null rc-update del filebrowser &>/dev/null || true
rm -f "$SERVICE_PATH" rm -f "$SERVICE_PATH"
fi fi
rm -f "$INSTALL_PATH" "$CONFIG_PATH" rm -f "$INSTALL_PATH" "$CONFIG_PATH" "$HOME/.filebrowser-quantum"
msg_ok "${APP} has been uninstalled." msg_ok "${APP} has been uninstalled."
exit 0 exit 0
fi fi
echo -n "Update ${APP}? (y/N): " echo -n "${TAB}Update ${APP}? (y/N): "
read -r update_prompt read -r update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
if check_for_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser"; then
msg_info "Updating ${APP}" msg_info "Updating ${APP}"
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi if ! command -v curl &>/dev/null; then $STD $PKG_MANAGER curl; fi
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN" fetch_and_deploy_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser" "singlefile" "latest" "/usr/local/bin" "linux-$(arch_resolve)-filebrowser"
chmod +x "$TMP_BIN" mv -f /usr/local/bin/filebrowser-quantum "$INSTALL_PATH"
mv -f "$TMP_BIN" /usr/local/bin/filebrowser
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
fi
exit 0 exit 0
else else
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}" msg_warn "Update skipped. Exiting."
exit 0 exit 0
fi fi
fi fi
echo -e "${YW}⚠️ ${APP} is not installed.${CL}" msg_warn "${APP} is not installed."
echo -n "Enter port number (Default: ${DEFAULT_PORT}): " echo -n "${TAB}Enter port number (Default: ${DEFAULT_PORT}): "
read -r PORT read -r PORT
PORT=${PORT:-$DEFAULT_PORT} PORT=${PORT:-$DEFAULT_PORT}
echo -n "Install ${APP}? (y/n): " echo -n "${TAB}Install ${APP}? (y/n): "
read -r install_prompt read -r install_prompt
if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}" msg_warn "Installation skipped. Exiting."
exit 0 exit 0
fi fi
msg_info "Installing ${APP} on ${OS}" msg_info "Installing ${APP} on ${OS}"
$PKG_MANAGER curl ffmpeg &>/dev/null $STD $PKG_MANAGER \
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN" curl \
chmod +x "$TMP_BIN" ffmpeg
mv -f "$TMP_BIN" /usr/local/bin/filebrowser 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"
msg_ok "Installed ${APP}" msg_ok "Installed ${APP}"
msg_info "Preparing configuration directory" msg_info "Preparing configuration directory"
@@ -167,7 +149,7 @@ chown root:root /usr/local/community-scripts
chmod 755 /usr/local/community-scripts chmod 755 /usr/local/community-scripts
msg_ok "Directory prepared" msg_ok "Directory prepared"
echo -n "Use No Authentication? (y/N): " echo -n "${TAB}Use No Authentication? (y/N): "
read -r noauth_prompt read -r noauth_prompt
# === YAML CONFIG GENERATION === # === YAML CONFIG GENERATION ===
@@ -251,9 +233,9 @@ depend() {
} }
EOF EOF
chmod +x "$SERVICE_PATH" chmod +x "$SERVICE_PATH"
rc-update add filebrowser default &>/dev/null $STD rc-update add filebrowser default
rc-service filebrowser start &>/dev/null $STD rc-service filebrowser start
fi fi
msg_ok "Service created successfully" msg_ok "Service created successfully"
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}" msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
+50 -75
View File
@@ -5,53 +5,40 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://filebrowser.org/ | Github: https://github.com/filebrowser/filebrowser # 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="FileBrowser"
APP_TYPE="addon"
INSTALL_PATH="/usr/local/bin/filebrowser" INSTALL_PATH="/usr/local/bin/filebrowser"
DB_PATH="/usr/local/community-scripts/filebrowser.db" DB_PATH="/usr/local/community-scripts/filebrowser.db"
DEFAULT_PORT=8080 DEFAULT_PORT=8080
# Telemetry 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser" "addon"
# Get first non-loopback IP & Detect primary network interface dynamically # Enable error handling
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}') set -Eeuo pipefail
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1) trap 'error_handler' ERR
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}') # Initialize all core functions (colors, formatting, icons, STD mode)
[[ -z "$IP" ]] && IP="127.0.0.1" load_functions
header_info
get_lxc_ip
IP="$LOCAL_IP"
# Proxmox Host Warning # Proxmox Host Warning
if [[ -d "/etc/pve" ]]; then if [[ -d "/etc/pve" ]]; then
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}" msg_warn "Running this addon directly on the Proxmox host is not recommended!"
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}" msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}" msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}" msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
echo "" echo ""
echo -n "Continue anyway on the Proxmox host? (y/N): " echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
read -r host_confirm read -r host_confirm
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
echo -e "${YW}Aborted.${CL}" msg_error "Aborted."
exit 0 exit 0
fi fi
fi fi
@@ -64,71 +51,59 @@ if [[ -f "/etc/alpine-release" ]]; then
elif [[ -f "/etc/debian_version" ]]; then elif [[ -f "/etc/debian_version" ]]; then
OS="Debian" OS="Debian"
SERVICE_PATH="/etc/systemd/system/filebrowser.service" SERVICE_PATH="/etc/systemd/system/filebrowser.service"
PKG_MANAGER="apt-get install -y" PKG_MANAGER="apt install -y"
else else
echo -e "${CROSS} Unsupported OS detected. Exiting." msg_error "Unsupported OS detected. Exiting."
exit 238 exit 238
fi 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 if [ -f "$INSTALL_PATH" ]; then
echo -e "${YW}⚠️ ${APP} is already installed.${CL}" msg_warn "${APP} is already installed."
read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Uninstalling ${APP}" msg_info "Uninstalling ${APP}"
if [[ "$OS" == "Debian" ]]; then if [[ "$OS" == "Debian" ]]; then
systemctl disable --now filebrowser.service &>/dev/null systemctl disable --now filebrowser.service &>/dev/null || true
rm -f "$SERVICE_PATH" rm -f "$SERVICE_PATH"
else else
rc-service filebrowser stop &>/dev/null rc-service filebrowser stop &>/dev/null || true
rc-update del filebrowser &>/dev/null rc-update del filebrowser &>/dev/null || true
rm -f "$SERVICE_PATH" rm -f "$SERVICE_PATH"
fi fi
rm -f "$INSTALL_PATH" "$DB_PATH" rm -f "$INSTALL_PATH" "$DB_PATH" "$HOME/.filebrowser"
msg_ok "${APP} has been uninstalled." msg_ok "${APP} has been uninstalled."
exit 0 exit 0
fi fi
read -r -p "Would you like to update ${APP}? (y/N): " update_prompt read -r -p "Would you like to update ${APP}? (y/N): " update_prompt
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
if check_for_gh_release "filebrowser" "filebrowser/filebrowser"; then
msg_info "Updating ${APP}" msg_info "Updating ${APP}"
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi fetch_and_deploy_gh_release "filebrowser" "filebrowser/filebrowser" "prebuild" "latest" "/opt/filebrowser-dist" "linux-$(arch_resolve)-filebrowser.tar.gz"
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null install -m 755 /opt/filebrowser-dist/filebrowser "$INSTALL_PATH"
chmod +x "$INSTALL_PATH" rm -rf /opt/filebrowser-dist
msg_ok "Updated ${APP}" msg_ok "Updated ${APP}"
fi
exit 0 exit 0
else else
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}" msg_warn "Update skipped. Exiting."
exit 0 exit 0
fi fi
fi fi
echo -e "${YW}⚠️ ${APP} is not installed.${CL}" msg_warn "${APP} is not installed."
read -r -p "Enter port number (Default: ${DEFAULT_PORT}): " PORT read -r -p "Enter port number (Default: ${DEFAULT_PORT}): " PORT
PORT=${PORT:-$DEFAULT_PORT} PORT=${PORT:-$DEFAULT_PORT}
read -r -p "Would you like to install ${APP}? (y/n): " install_prompt read -r -p "Would you like to install ${APP}? (y/n): " install_prompt
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing ${APP} on ${OS}" msg_info "Installing ${APP} on ${OS}"
$PKG_MANAGER wget tar curl &>/dev/null $STD $PKG_MANAGER \
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null tar \
chmod +x "$INSTALL_PATH" 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
msg_ok "Installed ${APP}" msg_ok "Installed ${APP}"
msg_info "Creating FileBrowser directory" msg_info "Creating FileBrowser directory"
@@ -144,19 +119,19 @@ if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Configuring No Authentication" msg_info "Configuring No Authentication"
cd /usr/local/community-scripts cd /usr/local/community-scripts
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null $STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null $STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
filebrowser config set --auth.method=noauth --database "$DB_PATH" &>/dev/null $STD filebrowser config set --auth.method=noauth --database "$DB_PATH"
if ! filebrowser users update 1 --perm.admin --database "$DB_PATH" &>/dev/null; then if ! filebrowser users update 1 --perm.admin --database "$DB_PATH" &>/dev/null; then
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null $STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
fi fi
msg_ok "No Authentication configured" msg_ok "No Authentication configured"
else else
msg_info "Setting up default authentication" msg_info "Setting up default authentication"
cd /usr/local/community-scripts cd /usr/local/community-scripts
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null $STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null $STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null $STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
msg_ok "Default authentication configured (admin:community-scripts.org)" msg_ok "Default authentication configured (admin:community-scripts.org)"
fi fi
@@ -194,13 +169,13 @@ depend() {
} }
EOF EOF
chmod +x "$SERVICE_PATH" chmod +x "$SERVICE_PATH"
rc-update add filebrowser default &>/dev/null $STD rc-update add filebrowser default
rc-service filebrowser start &>/dev/null $STD rc-service filebrowser start
fi fi
msg_ok "Service created successfully" msg_ok "Service created successfully"
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}" msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
else else
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}" msg_warn "Installation skipped. Exiting."
exit 0 exit 0
fi fi
+31 -50
View File
@@ -5,55 +5,37 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://nicolargo.github.io/glances/ | Github: https://github.com/nicolargo/glances # Source: https://nicolargo.github.io/glances/ | Github: https://github.com/nicolargo/glances
function header_info {
clear
cat <<"EOF"
________
/ ____/ /___ _____ ________ _____
/ / __/ / __ `/ __ \/ ___/ _ \/ ___/
/ /_/ / / /_/ / / / / /__/ __(__ )
\____/_/\__,_/_/ /_/\___/\___/____/
EOF
}
APP="Glances" APP="Glances"
YW=$(echo "\033[33m") APP_TYPE="addon"
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}"; } source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; } source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; } 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "glances" "addon"
get_lxc_ip() { # Enable error handling
if command -v hostname >/dev/null 2>&1 && hostname -I 2>/dev/null; then set -Eeuo pipefail
hostname -I | awk '{print $1}' trap 'error_handler' ERR
elif command -v ip >/dev/null 2>&1; then
ip -4 addr show scope global | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1 # Initialize all core functions (colors, formatting, icons, STD mode)
else load_functions
echo "127.0.0.1"
fi header_info
} get_lxc_ip
IP=$(get_lxc_ip) IP="$LOCAL_IP"
install_glances_debian() { install_glances_debian() {
msg_info "Installing dependencies" msg_info "Installing dependencies"
apt-get update >/dev/null 2>&1 $STD apt update
apt-get install -y gcc lm-sensors wireless-tools curl >/dev/null 2>&1 $STD apt install -y \
gcc \
lm-sensors \
wireless-tools \
curl
msg_ok "Installed dependencies" msg_ok "Installed dependencies"
msg_info "Setting up Python + uv" 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" setup_uv PYTHON_VERSION="3.12"
msg_ok "Setup Python + uv" msg_ok "Setup Python + uv"
@@ -61,10 +43,10 @@ install_glances_debian() {
cd /opt cd /opt
mkdir -p glances mkdir -p glances
cd glances cd glances
uv venv --clear $STD uv venv --clear
source .venv/bin/activate >/dev/null 2>&1 source .venv/bin/activate >/dev/null 2>&1
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1 $STD uv pip install --upgrade pip wheel setuptools
uv pip install "glances[web]" >/dev/null 2>&1 $STD uv pip install "glances[web]"
deactivate deactivate
msg_ok "Installed $APP" msg_ok "Installed $APP"
@@ -86,7 +68,7 @@ EOF
systemctl enable -q --now glances systemctl enable -q --now glances
msg_ok "Created systemd service" msg_ok "Created systemd service"
echo -e "\n$APP is now running at: http://$IP:61208\n" msg_ok "$APP is now running at: http://${IP}:61208"
} }
# update on Debian/Ubuntu # update on Debian/Ubuntu
@@ -98,7 +80,7 @@ update_glances_debian() {
msg_info "Updating $APP" msg_info "Updating $APP"
cd /opt/glances cd /opt/glances
source .venv/bin/activate source .venv/bin/activate
uv pip install --upgrade "glances[web]" >/dev/null 2>&1 $STD uv pip install --upgrade "glances[web]"
deactivate deactivate
systemctl restart glances systemctl restart glances
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
@@ -116,14 +98,13 @@ uninstall_glances_debian() {
# install on Alpine # install on Alpine
install_glances_alpine() { install_glances_alpine() {
msg_info "Installing dependencies" msg_info "Installing dependencies"
apk update >/dev/null 2>&1 $STD apk update
$STD apk add --no-cache \ $STD apk add --no-cache \
gcc musl-dev linux-headers python3-dev \ gcc musl-dev linux-headers python3-dev \
python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl >/dev/null 2>&1 python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl
msg_ok "Installed dependencies" msg_ok "Installed dependencies"
msg_info "Setting up Python + uv" 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" setup_uv PYTHON_VERSION="3.12"
msg_ok "Setup Python + uv" msg_ok "Setup Python + uv"
@@ -131,10 +112,10 @@ install_glances_alpine() {
cd /opt cd /opt
mkdir -p glances mkdir -p glances
cd glances cd glances
uv venv --clear $STD uv venv --clear
source .venv/bin/activate source .venv/bin/activate
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1 $STD uv pip install --upgrade pip wheel setuptools
uv pip install "glances[web]" >/dev/null 2>&1 $STD uv pip install "glances[web]"
deactivate deactivate
msg_ok "Installed $APP" msg_ok "Installed $APP"
@@ -165,7 +146,7 @@ update_glances_alpine() {
msg_info "Updating $APP" msg_info "Updating $APP"
cd /opt/glances cd /opt/glances
source .venv/bin/activate source .venv/bin/activate
uv pip install --upgrade "glances[web]" >/dev/null 2>&1 $STD uv pip install --upgrade "glances[web]"
deactivate deactivate
rc-service glances restart rc-service glances restart
msg_ok "Updated successfully!" msg_ok "Updated successfully!"
+5 -26
View File
@@ -7,8 +7,8 @@
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt 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/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/tools.func)
@@ -32,21 +32,6 @@ DEFAULT_PORT=3000
# Initialize all core functions (colors, formatting, icons, $STD mode) # Initialize all core functions (colors, formatting, icons, $STD mode)
load_functions load_functions
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
____ _ __ ____
/ _/___ ___ ____ ___ (_)____/ /_ / __ \_________ _ ____ __
/ // __ `__ \/ __ `__ \/ / ___/ __ \______/ /_/ / ___/ __ \| |/_/ / / /
_/ // / / / / / / / / / / / /__/ / / /_____/ ____/ / / /_/ /> </ /_/ /
/___/_/ /_/ /_/_/ /_/ /_/_/\___/_/ /_/ /_/ /_/ \____/_/|_|\__, /
/____/
EOF
}
# ============================================================================== # ==============================================================================
# OS DETECTION # OS DETECTION
# ============================================================================== # ==============================================================================
@@ -83,19 +68,13 @@ function update() {
systemctl stop immich-proxy.service &>/dev/null || true systemctl stop immich-proxy.service &>/dev/null || true
msg_ok "Stopped service" msg_ok "Stopped service"
msg_info "Backing up configuration" BACKUP_DIR="/opt/immich-public-proxy_backup"
cp "$CONFIG_PATH"/.env /tmp/ipp.env.bak 2>/dev/null || true create_backup "$CONFIG_PATH"/.env "$CONFIG_PATH"/config.json
cp "$CONFIG_PATH"/config.json /tmp/ipp.config.json.bak 2>/dev/null || true
msg_ok "Backed up configuration"
NODE_VERSION="24" setup_nodejs NODE_VERSION="24" setup_nodejs
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Immich Public Proxy" "alangrainger/immich-public-proxy" "tarball" "latest" "$INSTALL_PATH" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Immich Public Proxy" "alangrainger/immich-public-proxy" "tarball" "latest" "$INSTALL_PATH"
msg_info "Restoring configuration" restore_backup
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" msg_info "Installing dependencies"
cd "$CONFIG_PATH" cd "$CONFIG_PATH"
+5 -24
View File
@@ -7,8 +7,8 @@
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2 printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
apt-get update >/dev/null 2>&1 apt update >/dev/null 2>&1
apt-get install -y curl >/dev/null 2>&1 apt 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/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/tools.func)
@@ -32,21 +32,6 @@ DEFAULT_PORT=3000
# Initialize all core functions (colors, formatting, icons, STD mode) # Initialize all core functions (colors, formatting, icons, STD mode)
load_functions load_functions
# ==============================================================================
# HEADER
# ==============================================================================
function header_info {
clear
cat <<"EOF"
__ ____ __ __
/ /__ / / /_ _______/ /_____ _/ /_
__ / / _ \/ / / / / / ___/ __/ __ `/ __/
/ /_/ / __/ / / /_/ (__ ) /_/ /_/ / /_
\____/\___/_/_/\__, /____/\__/\__,_/\__/
/____/
EOF
}
# ============================================================================== # ==============================================================================
# OS DETECTION # OS DETECTION
# ============================================================================== # ==============================================================================
@@ -102,16 +87,12 @@ function update() {
systemctl stop jellystat.service &>/dev/null || true systemctl stop jellystat.service &>/dev/null || true
msg_ok "Stopped service" msg_ok "Stopped service"
msg_info "Backing up configuration" BACKUP_DIR="/opt/jellystat_backup"
cp "$CONFIG_PATH" /tmp/jellystat.env.bak 2>/dev/null || true create_backup "$CONFIG_PATH"
msg_ok "Backed up configuration"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
msg_info "Restoring configuration" restore_backup
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" msg_info "Installing dependencies"
cd "$INSTALL_PATH" cd "$INSTALL_PATH"
+34 -78
View File
@@ -5,6 +5,22 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.netdata.cloud/ | Github: https://github.com/netdata/netdata # Source: https://www.netdata.cloud/ | Github: https://github.com/netdata/netdata
APP="Netdata"
APP_TYPE="addon"
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 "netdata" "addon"
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
function header_info { function header_info {
clear clear
cat <<"EOF" cat <<"EOF"
@@ -17,63 +33,6 @@ function header_info {
EOF 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"
set -e
header_info
echo "Loading..."
function msg_info() {
local msg="$1"
echo -ne " ${HOLD} ${YW}${msg}..."
}
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.09.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.08.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.09.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.09.x"
exit 105
}
detect_codename() { detect_codename() {
source /etc/os-release source /etc/os-release
if [[ "$ID" != "debian" ]]; then if [[ "$ID" != "debian" ]]; then
@@ -99,7 +58,7 @@ get_latest_repo_pkg() {
install() { install() {
header_info header_info
while true; do while true; do
read -p "Are you sure you want to install NetData on Proxmox VE host. Proceed(y/n)? " yn read -r -p "Are you sure you want to install ${APP} on Proxmox VE host. Proceed(y/n)? " yn
case $yn in case $yn in
[Yy]*) break ;; [Yy]*) break ;;
[Nn]*) exit ;; [Nn]*) exit ;;
@@ -107,56 +66,53 @@ install() {
esac esac
done done
read -r -p "Verbose mode? <y/N> " prompt
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
CODENAME=$(detect_codename) CODENAME=$(detect_codename)
REPO_URL="https://repo.netdata.cloud/repos/repoconfig/debian/${CODENAME}/" REPO_URL="https://repo.netdata.cloud/repos/repoconfig/debian/${CODENAME}/"
msg_info "Setting up repository" msg_info "Setting up repository"
$STD apt-get install -y debian-keyring $STD apt install -y debian-keyring
PKG=$(get_latest_repo_pkg "$REPO_URL") PKG=$(get_latest_repo_pkg "$REPO_URL")
if [[ -z "$PKG" ]]; then if [[ -z "$PKG" ]]; then
msg_error "Could not find netdata-repo package for Debian $CODENAME" msg_error "Could not find netdata-repo package for Debian $CODENAME"
exit 237 exit 237
fi fi
curl -fsSL "${REPO_URL}${PKG}" -o "$PKG" TMP_DEB=$(mktemp --suffix=.deb)
$STD dpkg -i "$PKG" curl -fsSL "${REPO_URL}${PKG}" -o "$TMP_DEB"
rm -f "$PKG" $STD dpkg -i "$TMP_DEB"
rm -f "$TMP_DEB"
msg_ok "Set up repository" msg_ok "Set up repository"
msg_info "Installing Netdata" msg_info "Installing ${APP}"
$STD apt-get update $STD apt update
$STD apt-get install -y netdata $STD apt install -y netdata
msg_ok "Installed Netdata" msg_ok "Installed ${APP}"
msg_ok "Completed successfully!\n" msg_ok "Completed successfully!\n"
echo -e "\n Netdata should be reachable at${BL} http://$(hostname -I | awk '{print $1}'):19999 ${CL}\n" get_lxc_ip
echo -e "\n${APP} should be reachable at${BL} http://${LOCAL_IP}:19999 ${CL}\n"
} }
uninstall() { uninstall() {
header_info header_info
read -r -p "Verbose mode? <y/N> " prompt
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
msg_info "Uninstalling Netdata" msg_info "Uninstalling ${APP}"
systemctl stop netdata || true systemctl stop netdata || true
rm -rf /var/log/netdata /var/lib/netdata /var/cache/netdata /etc/netdata/go.d 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 rm -rf /etc/apt/trusted.gpg.d/netdata-archive-keyring.gpg /etc/apt/sources.list.d/netdata.list
$STD apt-get remove --purge -y netdata netdata-repo $STD apt remove --purge -y netdata netdata-repo
systemctl daemon-reload systemctl daemon-reload
$STD apt autoremove -y $STD apt autoremove -y
$STD userdel netdata || true $STD userdel netdata || true
msg_ok "Uninstalled Netdata" msg_ok "Uninstalled ${APP}"
msg_ok "Completed successfully!\n" msg_ok "Completed successfully!\n"
} }
header_info header_info
pve_check pve_check
OPTIONS=(Install "Install NetData on Proxmox VE" OPTIONS=(Install "Install ${APP} on Proxmox VE"
Uninstall "Uninstall NetData from Proxmox VE") Uninstall "Uninstall ${APP} from Proxmox VE")
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "NetData" \ CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP}" \
--menu "Select an option:" 10 58 2 "${OPTIONS[@]}" 3>&1 1>&2 2>&3) --menu "Select an option:" 10 58 2 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
case $CHOICE in case $CHOICE in
+101 -48
View File
@@ -5,67 +5,120 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://docs.olivetin.app/ | Github: https://github.com/OliveTin/OliveTin # Source: https://docs.olivetin.app/ | Github: https://github.com/OliveTin/OliveTin
function header_info {
clear
cat <<"EOF"
____ ___ _______
/ __ \/ (_) _____/_ __(_)___
/ / / / / / | / / _ \/ / / / __ \
/ /_/ / / /| |/ / __/ / / / / / /
\____/_/_/ |___/\___/_/ /_/_/ /_/
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" APP="OliveTin"
hostname="$(hostname)" APP_TYPE="addon"
# Telemetry 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "olivetin" "addon"
set-e # Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
header_info 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 while true; do
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
read -r yn
case $yn in case $yn in
[Yy]*) break ;; [Yy]*) break ;;
[Nn]*) exit ;; [Nn]*) exit ;;
*) echo "Please answer yes or no." ;; *) echo "Please answer yes or no." ;;
esac esac
done done
unset _HEADER_SHOWN
header_info header_info
function msg_info() { install
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"
+53 -63
View File
@@ -5,39 +5,26 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.phpmyadmin.net/ | Github: https://github.com/phpmyadmin/phpmyadmin # 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="phpMyAdmin"
APP_TYPE="addon"
INSTALL_DIR_DEBIAN="/var/www/html/phpMyAdmin" INSTALL_DIR_DEBIAN="/var/www/html/phpMyAdmin"
INSTALL_DIR_ALPINE="/usr/share/phpmyadmin" INSTALL_DIR_ALPINE="/usr/share/phpmyadmin"
# Telemetry 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 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" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "phpmyadmin" "addon"
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}') # Enable error handling
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1) set -Eeuo pipefail
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}') trap 'error_handler' ERR
[[ -z "$IP" ]] && IP="127.0.0.1"
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
get_lxc_ip
IP="$LOCAL_IP"
# Detect OS # Detect OS
if [[ -f "/etc/alpine-release" ]]; then if [[ -f "/etc/alpine-release" ]]; then
@@ -47,24 +34,20 @@ if [[ -f "/etc/alpine-release" ]]; then
INSTALL_DIR="$INSTALL_DIR_ALPINE" INSTALL_DIR="$INSTALL_DIR_ALPINE"
elif [[ -f "/etc/debian_version" ]]; then elif [[ -f "/etc/debian_version" ]]; then
OS="Debian" OS="Debian"
PKG_MANAGER_INSTALL="apt-get install -y" PKG_MANAGER_INSTALL="apt install -y"
PKG_QUERY="dpkg -l" PKG_QUERY="dpkg -l"
INSTALL_DIR="$INSTALL_DIR_DEBIAN" INSTALL_DIR="$INSTALL_DIR_DEBIAN"
else else
echo -e "${CROSS} Unsupported OS detected. Exiting." msg_error "Unsupported OS detected. Exiting."
exit 238 exit 238
fi fi
header_info 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() { function check_internet() {
if ! command -v curl &>/dev/null; then if ! command -v curl &>/dev/null; then
apt-get update >/dev/null 2>&1 $STD apt update
apt-get install -y curl >/dev/null 2>&1 $STD apt install -y curl
fi fi
msg_info "Checking Internet connectivity to GitHub" msg_info "Checking Internet connectivity to GitHub"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://github.com) HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
@@ -103,7 +86,7 @@ function install_php_and_modules() {
done done
if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then
msg_info "Installing missing PHP packages: ${MISSING_PACKAGES[*]}" msg_info "Installing missing PHP packages: ${MISSING_PACKAGES[*]}"
if ! apt-get update &>/dev/null || ! apt-get install -y "${MISSING_PACKAGES[@]}" &>/dev/null; then if ! $STD apt update || ! $STD apt install -y "${MISSING_PACKAGES[@]}"; then
msg_error "Failed to install required PHP modules. Exiting." msg_error "Failed to install required PHP modules. Exiting."
exit 237 exit 237
fi fi
@@ -113,30 +96,41 @@ function install_php_and_modules() {
fi fi
else else
msg_info "Installing Lighttpd and PHP for Alpine" msg_info "Installing Lighttpd and PHP for Alpine"
$PKG_MANAGER_INSTALL lighttpd php php-fpm php-session php-json php-mysqli curl tar openssl &>/dev/null $STD $PKG_MANAGER_INSTALL \
lighttpd \
php \
php-fpm \
php-session \
php-json \
php-mysqli \
curl \
tar \
openssl
msg_ok "Installed Lighttpd and PHP" msg_ok "Installed Lighttpd and PHP"
fi fi
} }
function install_phpmyadmin() { function install_phpmyadmin() {
msg_info "Fetching latest phpMyAdmin release from GitHub" msg_info "Fetching latest phpMyAdmin release from GitHub"
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4) LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g') LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
if [[ -z "$LATEST_VERSION" ]]; then 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="RELEASE_5_2_2" LATEST_VERSION="5.2.2"
fi fi
msg_ok "Latest version: $LATEST_VERSION" msg_ok "Latest version: $LATEST_VERSION"
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz" TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
msg_info "Downloading ${TARBALL_URL}" msg_info "Downloading ${TARBALL_URL}"
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then tarball=$(mktemp)
if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
msg_error "Download failed: $TARBALL_URL" msg_error "Download failed: $TARBALL_URL"
exit 115 exit 115
fi fi
mkdir -p "$INSTALL_DIR" mkdir -p "$INSTALL_DIR"
tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C "$INSTALL_DIR" tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
rm -f "$tarball"
} }
function configure_phpmyadmin() { function configure_phpmyadmin() {
@@ -223,7 +217,7 @@ function uninstall_phpmyadmin() {
function update_phpmyadmin() { function update_phpmyadmin() {
msg_info "Fetching latest phpMyAdmin release from GitHub" msg_info "Fetching latest phpMyAdmin release from GitHub"
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4) LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g') LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
if [[ -z "$LATEST_VERSION" ]]; then if [[ -z "$LATEST_VERSION" ]]; then
@@ -234,36 +228,32 @@ function update_phpmyadmin() {
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz" TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
msg_info "Downloading ${TARBALL_URL}" msg_info "Downloading ${TARBALL_URL}"
tarball=$(mktemp)
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
msg_error "Download failed: $TARBALL_URL" msg_error "Download failed: $TARBALL_URL"
exit 115 exit 115
fi fi
BACKUP_DIR="/tmp/phpmyadmin-backup-$(date +%Y%m%d-%H%M%S)" BACKUP_DIR="/opt/phpmyadmin_backup"
mkdir -p "$BACKUP_DIR" create_backup \
BACKUP_ITEMS=("config.inc.php" "upload" "save" "tmp" "themes") "$INSTALL_DIR/config.inc.php" \
"$INSTALL_DIR/upload" \
"$INSTALL_DIR/save" \
"$INSTALL_DIR/tmp" \
"$INSTALL_DIR/themes"
msg_info "Backing up existing phpMyAdmin data" tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
for item in "${BACKUP_ITEMS[@]}"; do rm -f "$tarball"
[[ -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" msg_ok "Extracted phpMyAdmin $LATEST_VERSION"
msg_info "Restoring preserved files" restore_backup
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 configure_phpmyadmin
} }
if is_phpmyadmin_installed; then if is_phpmyadmin_installed; then
echo -e "${YW}⚠️ ${APP} is already installed at ${INSTALL_DIR}.${CL}" msg_warn "${APP} is already installed at ${INSTALL_DIR}."
read -r -p "Would you like to Update (1), Uninstall (2) or Cancel (3)? [1/2/3]: " action read -r -p "Would you like to Update (1), Uninstall (2) or Cancel (3)? [1/2/3]: " action
action="${action//[[:space:]]/}" action="${action//[[:space:]]/}"
case "$action" in case "$action" in
@@ -275,11 +265,11 @@ if is_phpmyadmin_installed; then
uninstall_phpmyadmin uninstall_phpmyadmin
;; ;;
3) 3)
echo -e "${YW}⚠️ Action cancelled. Exiting.${CL}" msg_warn "Action cancelled. Exiting."
exit 0 exit 0
;; ;;
*) *)
echo -e "${YW}⚠️ Invalid input. Exiting.${CL}" msg_warn "Invalid input. Exiting."
exit 112 exit 112
;; ;;
esac esac
@@ -292,12 +282,12 @@ else
install_phpmyadmin install_phpmyadmin
configure_phpmyadmin configure_phpmyadmin
if [[ "$OS" == "Debian" ]]; then if [[ "$OS" == "Debian" ]]; then
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}" msg_ok "${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}"
else else
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/${CL}" msg_ok "${APP} is reachable at: ${BL}http://${IP}/${CL}"
fi fi
else else
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}" msg_warn "Installation skipped. Exiting."
exit 0 exit 0
fi fi
fi fi
+38 -47
View File
@@ -5,40 +5,30 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://pyenv.run/ | Github: https://github.com/pyenv/pyenv # Source: https://pyenv.run/ | Github: https://github.com/pyenv/pyenv
set -e APP="pyenv"
YW=$(echo "\033[33m") APP_TYPE="addon"
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}..."
}
function msg_ok() { source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
local msg="$1" source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
echo -e "${BFR} ${CM} ${GN}${msg}${CL}" source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
}
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 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" 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
if command -v pveversion >/dev/null 2>&1; then if command -v pveversion >/dev/null 2>&1; then
msg_error "Can't Install on Proxmox " msg_error "Can't Install on Proxmox "
exit exit 1
fi fi
msg_info "Installing pyenv" get_lxc_ip
apt-get install -y \ msg_info "Installing ${APP}"
$STD apt update
$STD apt install -y \
make \ make \
build-essential \ build-essential \
libjpeg-dev \ libjpeg-dev \
@@ -62,18 +52,18 @@ apt-get install -y \
libopenjp2-7 \ libopenjp2-7 \
libtiff5 \ libtiff5 \
libturbojpeg0-dev \ libturbojpeg0-dev \
liblzma-dev &>/dev/null liblzma-dev
git clone https://github.com/pyenv/pyenv.git ~/.pyenv &>/dev/null $STD git clone https://github.com/pyenv/pyenv.git ~/.pyenv
set +e set +Eeuo pipefail
echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >>~/.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 echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >>~/.bashrc
msg_ok "Installed pyenv" msg_ok "Installed ${APP}"
. ~/.bashrc . ~/.bashrc
set -e set -Eeuo pipefail
msg_info "Installing Python 3.11.1" msg_info "Installing Python 3.11.1"
pyenv install 3.11.1 &>/dev/null $STD pyenv install 3.11.1
pyenv global 3.11.1 pyenv global 3.11.1
msg_ok "Installed Python 3.11.1" msg_ok "Installed Python 3.11.1"
read -r -p "Would you like to install Home Assistant Beta? <y/N> " prompt read -r -p "Would you like to install Home Assistant Beta? <y/N> " prompt
@@ -95,13 +85,13 @@ EOF
cd /srv/homeassistant cd /srv/homeassistant
python3 -m venv . python3 -m venv .
source bin/activate source bin/activate
python3 -m pip install wheel &>/dev/null $STD python3 -m pip install wheel
pip3 install --upgrade pip &>/dev/null $STD pip3 install --upgrade pip
pip3 install psycopg2-binary &>/dev/null $STD pip3 install psycopg2-binary
pip3 install --pre homeassistant &>/dev/null $STD pip3 install --pre homeassistant
systemctl enable homeassistant &>/dev/null systemctl enable homeassistant &>/dev/null
msg_ok "Installed Home Assistant Beta" msg_ok "Installed Home Assistant Beta"
echo -e " Go to $(hostname -I | awk '{print $1}'):8123" echo -e " Go to ${LOCAL_IP}:8123"
hass hass
fi fi
@@ -112,9 +102,9 @@ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
cd /srv/esphome cd /srv/esphome
python3 -m venv . python3 -m venv .
source bin/activate source bin/activate
python3 -m pip install wheel &>/dev/null $STD python3 -m pip install wheel
pip3 install --upgrade pip &>/dev/null $STD pip3 install --upgrade pip
pip3 install --pre esphome &>/dev/null $STD pip3 install --pre esphome
cat <<EOF >/srv/esphome/start.sh cat <<EOF >/srv/esphome/start.sh
#!/usr/bin/env bash #!/usr/bin/env bash
@@ -143,25 +133,26 @@ WantedBy=multi-user.target
EOF EOF
systemctl enable --now esphomedashboard &>/dev/null systemctl enable --now esphomedashboard &>/dev/null
msg_ok "Installed ESPHome Beta" msg_ok "Installed ESPHome Beta"
echo -e " Go to $(hostname -I | awk '{print $1}'):6052" echo -e " Go to ${LOCAL_IP}:6052"
exec $SHELL exec $SHELL
fi fi
read -r -p "Would you like to install Matter-Server (Beta)? <y/N> " prompt read -r -p "Would you like to install Matter-Server (Beta)? <y/N> " prompt
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
msg_info "Installing Matter Server" msg_info "Installing Matter Server"
apt-get install -y \ $STD apt install -y \
libcairo2-dev \ libcairo2-dev \
libjpeg62-turbo-dev \ libjpeg62-turbo-dev \
libgirepository1.0-dev \ libgirepository1.0-dev \
libpango1.0-dev \ libpango1.0-dev \
libgif-dev \ libgif-dev \
g++ &>/dev/null g++
python3 -m pip install wheel $STD python3 -m pip install wheel
pip3 install --upgrade pip $STD pip3 install --upgrade pip
pip install python-matter-server[server] $STD pip install python-matter-server[server]
msg_ok "Installed Matter Server" msg_ok "Installed Matter Server"
echo -e "Start server > python -m matter_server.server" echo -e "Start server > python -m matter_server.server"
fi fi
msg_ok "\nFinished\n" msg_ok "\nFinished\n"
exec $SHELL exec $SHELL
+31 -39
View File
@@ -5,6 +5,22 @@
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://www.webmin.com/ | Github: https://github.com/webmin/webmin # Source: https://www.webmin.com/ | Github: https://github.com/webmin/webmin
APP="Webmin"
APP_TYPE="addon"
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 "webmin" "addon"
# Enable error handling
set -Eeuo pipefail
trap 'error_handler' ERR
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
function header_info { function header_info {
clear clear
cat <<"EOF" cat <<"EOF"
@@ -15,51 +31,27 @@ function header_info {
EOF 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"
header_info header_info
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Webmin Installer" --yesno "This Will Install Webmin on this LXC Container. Proceed?" 10 58 whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} Installer" --yesno "This Will Install ${APP} on this LXC Container. Proceed?" 10 58
msg_info "Installing Prerequisites" msg_info "Installing Prerequisites"
apt update &>/dev/null $STD apt update
apt-get -y install libnet-ssleay-perl libauthen-pam-perl libio-pty-perl unzip shared-mime-info curl &>/dev/null $STD apt install -y \
libnet-ssleay-perl \
libauthen-pam-perl \
libio-pty-perl \
unzip \
shared-mime-info \
curl
msg_ok "Installed Prerequisites" msg_ok "Installed Prerequisites"
LATEST=$(curl -fsSL https://api.github.com/repos/webmin/webmin/releases/latest | grep '"tag_name":' | cut -d'"' -f4) msg_info "Installing ${APP}"
fetch_and_deploy_gh_release "webmin" "webmin/webmin" "binary" "latest" "/opt/webmin" "webmin_*_all.deb"
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 /usr/share/webmin/changepass.pl /etc/webmin root root &>/dev/null
rm -rf /root/webmin_${LATEST}_all.deb msg_ok "Installed ${APP}"
msg_ok "Installed Webmin"
get_lxc_ip
echo -e "Successfully Installed!! ${APP} should be reachable by going to ${BL}https://${LOCAL_IP}:10000${CL}"
IP=$(hostname -I | cut -f1 -d ' ')
echo -e "Successfully Installed!! Webmin should be reachable by going to ${BL}https://${IP}:10000${CL}"