Compare commits

...

76 Commits

Author SHA1 Message Date
CanbiZ (MickLesk)
76df01dcc6 Refactor Home Assistant OS version selection and caching
Refactor advanced settings dialog for Home Assistant OS version selection and simplify image caching logic.
2026-09-15 13:02:20 +02:00
CanbiZ (MickLesk)
ead57f5df4 Modify author line in haos-vm.sh
Updated author information in the script header.
2026-09-15 12:23:19 +02:00
CanbiZ (MickLesk)
575e0eeab8 HomeAssistant-OS (VM): Refactor for improved readability
Refactor script to improve readability and maintainability. Updated function calls and variable assignments for better clarity.
2026-09-15 12:21:02 +02:00
community-scripts-pr-app[bot]
039e65d803 Update CHANGELOG.md (#17280)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 09:59:36 +00:00
community-scripts-pr-app[bot]
05dc593f99 Update CHANGELOG.md (#17274)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 07:53:02 +00:00
community-scripts-pr-app[bot]
a7d58ba5c7 Update CHANGELOG.md (#17272)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 07:17:09 +00:00
push-app-to-main[bot]
8a8c636a83 valhalla (#17231) 2026-09-15 09:16:43 +02:00
community-scripts-pr-app[bot]
7c851f766e Update CHANGELOG.md (#17271)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 07:16:39 +00:00
CanbiZ (MickLesk)
fbea9c04c3 monitor-all: decide on flag values, not on key presence (#17261) 2026-09-15 09:16:12 +02:00
community-scripts-pr-app[bot]
1e500043b7 Update CHANGELOG.md (#17270)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 06:48:14 +00:00
Connor Gallopo
dd421cec72 copy packages/emails into the tracearr deploy tree (#17268) 2026-09-15 08:47:51 +02:00
community-scripts-pr-app[bot]
e4d5fcede1 Update CHANGELOG.md (#17269)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 06:31:07 +00:00
Chris
91c6673ae0 Pin to v3.2.1 (#17264) 2026-09-15 08:30:40 +02:00
community-scripts-pr-app[bot]
787dbf2420 Update CHANGELOG.md (#17259)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-14 13:51:26 +00:00
push-app-to-main[bot]
2bac6ac611 Add borg-ui (ct) (#17258)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-09-14 15:50:54 +02:00
community-scripts-pr-app[bot]
7a36712ef4 Update CHANGELOG.md (#17257)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-14 10:53:55 +00:00
Raffaele Borrelli
f21bd26c8a fix(sparkyfitness): substitute NGINX_RATE_LIMIT in nginx config (#17256)
Co-authored-by: Raffaele Borrelli <r.borrelli@novomatic.it>
2026-09-14 12:53:28 +02:00
community-scripts-pr-app[bot]
e476e28e33 Update CHANGELOG.md (#17253)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-14 08:08:57 +00:00
github-actions[bot]
db50b50a63 spliit: bump Node.js from 24 to 26 (#17250)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-14 10:08:27 +02:00
community-scripts-pr-app[bot]
33a110f06a Update CHANGELOG.md (#17242)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-13 18:22:02 +00:00
community-scripts-pr-app[bot]
70091db00b Update CHANGELOG.md (#17241)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-13 18:08:12 +00:00
Copilot
8b02661dd0 Downgrade iobroker to Node 24 (#17229)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: MickLesk <47820557+MickLesk@users.noreply.github.com>
2026-09-13 20:07:45 +02:00
community-scripts-pr-app[bot]
9e25624107 Update CHANGELOG.md (#17233)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-13 00:05:14 +00:00
community-scripts-pr-app[bot]
e1a084edea Archive old changelog entries (#17232)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-13 00:04:44 +00:00
community-scripts-pr-app[bot]
e24a47ebca Update CHANGELOG.md (#17227)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 20:12:20 +00:00
community-scripts-pr-app[bot]
9e0a57a04a Update CHANGELOG.md (#17226)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 20:11:38 +00:00
push-app-to-main[bot]
2551a576d5 Elasticsearch (#17188) 2026-09-12 22:11:22 +02:00
community-scripts-pr-app[bot]
aa2d63f569 Update CHANGELOG.md (#17225)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 20:11:11 +00:00
community-scripts-pr-app[bot]
8348fb3cb3 Update CHANGELOG.md (#17224)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 20:10:59 +00:00
CanbiZ (MickLesk)
be0a8c3467 Add --no-sync to Paperless uv run services (#17210) 2026-09-12 22:10:47 +02:00
community-scripts-pr-app[bot]
1131d748e8 Update CHANGELOG.md (#17223)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 20:10:36 +00:00
CanbiZ (MickLesk)
764e4232ba Docker VM: Feature Bump - Refactor script for improved functionality (#17216) 2026-09-12 22:10:00 +02:00
community-scripts-pr-app[bot]
8ee86a91b8 Update CHANGELOG.md (#17218)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 15:18:08 +00:00
community-scripts-pr-app[bot]
95d80a4941 Update CHANGELOG.md (#17217)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 15:15:09 +00:00
community-scripts-pr-app[bot]
5f1b71a85e Update CHANGELOG.md (#17213)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 12:31:07 +00:00
eXistC
2c6a578343 fix(dispatcharr): add comskip installation and build dependencies (#16224) 2026-09-12 14:30:42 +02:00
community-scripts-pr-app[bot]
b068e7cd8a Update CHANGELOG.md (#17212)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 12:25:32 +00:00
Kevin Langhans
02cf8a0a8f feat(jitsi-meet): optional public setup (FQDN, Let's Encrypt, NAT, secure domain) (#17132)
Adds five optional var_jitsi_* settings to the install script. All default
to empty, which keeps the previous LAN-only behaviour (container IP,
self-signed certificate):

- var_jitsi_domain     public hostname instead of the container IP
- var_jitsi_le_email   Let's Encrypt via the packaged debconf option
- var_jitsi_public_ip  static NAT mapping in jvb.conf (JVB 2.3+)
- var_jitsi_admin_user secure domain: only authenticated users create rooms
- var_jitsi_admin_pass password for that user (generated when empty)

Tested on Proxmox VE 9.2 as unprivileged Debian 13 LXC, both with all
variables set (self-signed) and with none set.

Co-authored-by: klanghans <13657862+klanghans@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 14:25:09 +02:00
community-scripts-pr-app[bot]
9580c0f5bd Update CHANGELOG.md (#17211)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 12:24:23 +00:00
push-app-to-main[bot]
3dbfe54701 Add hammer (ct) (#17189)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-09-12 14:24:00 +02:00
community-scripts-pr-app[bot]
ab5f20ec71 Update CHANGELOG.md (#17207)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 10:01:49 +00:00
CanbiZ (MickLesk)
0a48435ef9 poznote: serve from src/public docroot (#17187) 2026-09-12 12:01:26 +02:00
community-scripts-pr-app[bot]
9e22ffe10d Update CHANGELOG.md (#17206)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 09:53:19 +00:00
push-app-to-main[bot]
4412cc0eae gotenberg (#17205)
* Add gotenberg (ct)

* Update messages in gotenberg.sh for clarity

* Implement unoconverter update in gotenberg.sh

* Fix formatting and add Go version setup in script

* Update Gotenberg installation script for Go version

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-09-12 11:52:55 +02:00
community-scripts-pr-app[bot]
fe823143fb Update CHANGELOG.md (#17204)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 06:31:53 +00:00
CanbiZ (MickLesk)
24e006cd81 calibre-web: use calibreweb release identifier to avoid version file collision (#17186) 2026-09-12 08:31:29 +02:00
community-scripts-pr-app[bot]
1b581bddea Update CHANGELOG.md (#17202)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 21:41:29 +00:00
push-app-to-main[bot]
c1fc07d937 Lemonade-Server (#17190)
* Add lemonade-server (ct)

* Enable ARM64 support by default in script

---------

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-09-11 23:40:58 +02:00
community-scripts-pr-app[bot]
c98008cc16 Update CHANGELOG.md (#17201)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 18:12:50 +00:00
thieneret
8713dabc56 update authentik to 2026.8.2 (#17198) 2026-09-11 20:12:18 +02:00
community-scripts-pr-app[bot]
6b30d4462d Update .app files (#17194)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2026-09-11 10:18:07 +02:00
community-scripts-pr-app[bot]
fc40e198b6 Update CHANGELOG.md (#17195)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 08:17:34 +00:00
push-app-to-main[bot]
b875f780bb Dockhand (#17191)
* Add dockhand (addon)

* Revise copyright and license details in dockhand.sh

---------

Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
Co-authored-by: Tobias <96661824+CrazyWolf13@users.noreply.github.com>
2026-09-11 10:17:05 +02:00
MickLesk
10ab064f26 formatting fix issue report 2026-09-11 08:37:28 +02:00
community-scripts-pr-app[bot]
db418a7a3b Update CHANGELOG.md (#17185)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:44:06 +00:00
community-scripts-pr-app[bot]
f17a8df641 Update CHANGELOG.md (#17184)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:43:55 +00:00
community-scripts-pr-app[bot]
0fa0a912ac Update CHANGELOG.md (#17183)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:43:37 +00:00
push-app-to-main[bot]
b9f7751590 OneTimeSecret (#17097) 2026-09-11 07:43:35 +02:00
community-scripts-pr-app[bot]
7c0283c73f Update CHANGELOG.md (#17182)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:43:29 +00:00
community-scripts-pr-app[bot]
5774100f05 Update CHANGELOG.md (#17181)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:43:11 +00:00
CanbiZ (MickLesk)
73a8c55c9d passwordpusher: restore data before running migrations (#17141) 2026-09-11 07:43:04 +02:00
community-scripts-pr-app[bot]
06115ca811 Update CHANGELOG.md (#17180)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:43:00 +00:00
community-scripts-pr-app[bot]
e00429ea7e Update CHANGELOG.md (#17179)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:42:44 +00:00
CanbiZ (MickLesk)
de9b2f7ff3 paperclip: install the rust toolchain needed by the runner build (#17142) 2026-09-11 07:42:37 +02:00
community-scripts-pr-app[bot]
2b541531f7 Update CHANGELOG.md (#17178)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:42:32 +00:00
CanbiZ (MickLesk)
c001360b2d Rename lxc-delete.sh to guest-delete.sh (#17152) 2026-09-11 07:42:12 +02:00
community-scripts-pr-app[bot]
b2f8add60f Update CHANGELOG.md (#17177)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:42:10 +00:00
community-scripts-pr-app[bot]
fe26465c2c Update CHANGELOG.md (#17176)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:41:48 +00:00
CanbiZ (MickLesk)
785d33be40 core.func: fall back to a usable HOME when the shell has none (#17154) 2026-09-11 07:41:44 +02:00
community-scripts-pr-app[bot]
28b4ae0b07 Update CHANGELOG.md (#17175)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:41:29 +00:00
CanbiZ (MickLesk)
e253713148 homepage: run next directly instead of through pnpm (#17155) 2026-09-11 07:41:21 +02:00
community-scripts-pr-app[bot]
5748b577c4 Update CHANGELOG.md (#17174)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:41:02 +00:00
CanbiZ (MickLesk)
7304dec635 update-apps: rewrite the retired Gitea base in every container before updating it (#17156) 2026-09-11 07:40:57 +02:00
CanbiZ (MickLesk)
28c18b735b issue template: add PVE release, execution context and phase; refresh distro list (#17160) 2026-09-11 07:40:36 +02:00
community-scripts-pr-app[bot]
46a3f05bfb Update CHANGELOG.md (#17173)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-11 05:39:47 +00:00
Tobias
433064a93f changedetection: fix: pin browserless (#17163) 2026-09-11 07:39:20 +02:00
62 changed files with 2257 additions and 1176 deletions

View File

@@ -6,13 +6,17 @@ body:
attributes: attributes:
value: | value: |
## ⚠️ **IMPORTANT - READ FIRST** ## ⚠️ **IMPORTANT - READ FIRST**
- 🔍 **Search first:** Before submitting, check if the issue has already been reported or resolved in [closed issues](https://github.com/community-scripts/ProxmoxVE/issues?q=is%3Aissue+is%3Aclosed). If found, comment on that issue instead of creating a new one.
Alternatively, check the **[Discussions](https://github.com/community-scripts/ProxmoxVE/discussions)** under the *"Announcement"* or *"Guide"* categories for relevant information.
- 🔎 If you encounter `[ERROR] in line 23: exit code *: while executing command "$@" > /dev/null 2>&1`, rerun the script with verbose mode before submitting the issue.
- 📜 **Read the script:** Familiarize yourself with the script's content and its purpose. This will help you understand the issue better and provide more relevant information
Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently. **1. Reproduce the issue with verbose mode - this is mandatory.**
Set `var_verbose=yes` (or *Advanced Settings → Verbose Mode*) and run the script again.
Only a verbose log shows what actually failed - a bare `[ERROR] in line 23: exit code *` tells us nothing.
**Reports without a verbose log will most likely be closed.**
**2. Search before you post.**
Check the [closed issues](https://github.com/community-scripts/ProxmoxVE/issues?q=is%3Aissue+is%3Aclosed) and the [Discussions](https://github.com/community-scripts/ProxmoxVE/discussions) (*Announcement* / *Guide*). If it is already known, comment there instead of opening a new issue.
**3. Read the script.**
Knowing what it does makes it much easier to describe the problem - and often to solve it yourself.
- type: input - type: input
id: guidelines id: guidelines
@@ -28,7 +32,6 @@ body:
label: 🔎 Did you run the script with verbose mode enabled? label: 🔎 Did you run the script with verbose mode enabled?
description: "Required for debugging any script issue. A verbose log is mandatory." description: "Required for debugging any script issue. A verbose log is mandatory."
options: options:
- ""
- "Yes, verbose mode was enabled and the output is included below" - "Yes, verbose mode was enabled and the output is included below"
- "No (this issue will likely be closed automatically)" - "No (this issue will likely be closed automatically)"
validations: validations:
@@ -50,6 +53,32 @@ body:
validations: validations:
required: true required: true
- type: dropdown
id: issue_phase
attributes:
label: 🕒 When does the issue occur?
options:
- "Initial creation / installation"
- "Update of an existing container"
- "While the application is running"
validations:
required: true
- type: dropdown
id: execution_context
attributes:
label: 🖱️ Where did you run the command?
description: "The shell matters — the Proxmox web console starts without some environment variables that a normal login shell sets."
options:
- "Proxmox web UI → node → Shell"
- "Proxmox web UI → LXC → Console"
- "SSH into the Proxmox host"
- "SSH into the container"
- "pct enter from the host"
- "Other / not listed"
validations:
required: true
- type: checkboxes - type: checkboxes
validations: validations:
required: true required: true
@@ -64,18 +93,31 @@ body:
value: "💡 **Tip:** If you are using Advanced Settings, please test with Default Settings before submitting an issue." value: "💡 **Tip:** If you are using Advanced Settings, please test with Default Settings before submitting an issue."
- type: dropdown - type: dropdown
id: linux_distribution id: os_distribution
attributes: attributes:
label: 🖥️ Which Linux distribution are you using? label: 🖥️ Which Linux distribution is the container running?
options: options:
- - Debian
- Ubuntu
- Alpine - Alpine
- Debian 11 - Devuan
- Debian 12 - AlmaLinux
- Debian 13 - Rocky Linux
- Ubuntu 22.04 - CentOS Stream
- Ubuntu 24.04 - Fedora
- Ubuntu 24.10 - openSUSE
- openEuler
- Gentoo
- Other / not listed
validations:
required: true
- type: input
id: os_version
attributes:
label: 🔢 Which version of that distribution?
description: "Run `cat /etc/os-release` inside the container if unsure."
placeholder: "e.g. 13 (Debian), 24.04 (Ubuntu), 3.22 (Alpine)"
validations: validations:
required: true required: true
@@ -85,16 +127,27 @@ body:
label: 🧱 Is this Proxmox host running arm64? label: 🧱 Is this Proxmox host running arm64?
description: "Run `dpkg --print-architecture` on your Proxmox host if unsure." description: "Run `dpkg --print-architecture` on your Proxmox host if unsure."
options: options:
- ""
- "No" - "No"
- "Yes" - "Yes"
validations: validations:
required: true required: true
- type: dropdown
id: pve_major
attributes:
label: 📈 Which Proxmox VE release are you on?
options:
- "Proxmox VE 9"
- "Proxmox VE 8"
- "Proxmox VE 7 or older (end of life)"
validations:
required: true
- type: input - type: input
id: pve_version id: pve_version
attributes: attributes:
label: 📈 Which Proxmox version are you on? label: 🔢 Exact Proxmox version and kernel
description: "Both matter — several issues turned out to be kernel-specific."
placeholder: "run pveversion in your PVE node console" placeholder: "run pveversion in your PVE node console"
validations: validations:
required: true required: true

166
.github/changelogs/2026/09.md generated vendored
View File

@@ -1,3 +1,169 @@
## 2026-09-12
### 🆕 New Scripts
- Elasticsearch ([#17188](https://github.com/community-scripts/ProxmoxVE/pull/17188))
- Hammer ([#17189](https://github.com/community-scripts/ProxmoxVE/pull/17189))
- gotenberg ([#17205](https://github.com/community-scripts/ProxmoxVE/pull/17205))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix(dispatcharr): add comskip installation and build dependencies [@eXistC](https://github.com/eXistC) ([#16224](https://github.com/community-scripts/ProxmoxVE/pull/16224))
- poznote: serve from src/public docroot [@MickLesk](https://github.com/MickLesk) ([#17187](https://github.com/community-scripts/ProxmoxVE/pull/17187))
- calibre-web: use calibreweb release identifier to avoid version file collision [@MickLesk](https://github.com/MickLesk) ([#17186](https://github.com/community-scripts/ProxmoxVE/pull/17186))
- #### ✨ New Features
- Docker VM: Feature Bump - Refactor script for improved functionality [@MickLesk](https://github.com/MickLesk) ([#17216](https://github.com/community-scripts/ProxmoxVE/pull/17216))
- feat(jitsi-meet): optional public setup (FQDN, Let's Encrypt, NAT, secure domain) [@klanghans](https://github.com/klanghans) ([#17132](https://github.com/community-scripts/ProxmoxVE/pull/17132))
- #### 🔧 Refactor
- Paperless-NGX: add --no-sync to uv run services [@MickLesk](https://github.com/MickLesk) ([#17210](https://github.com/community-scripts/ProxmoxVE/pull/17210))
### 💾 Core
- VM's: show the selected CPU model instead of doubling it [@MickLesk](https://github.com/MickLesk) ([core#37](https://github.com/community-scripts/core/pull/37))
- Generate app headers [@github-actions[bot]](https://github.com/github-actions[bot]) ([core#36](https://github.com/community-scripts/core/pull/36))
## 2026-09-11
### 🆕 New Scripts
- Lemonade-Server ([#17190](https://github.com/community-scripts/ProxmoxVE/pull/17190))
- OneTimeSecret ([#17097](https://github.com/community-scripts/ProxmoxVE/pull/17097))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- update authentik to 2026.8.2 [@thieneret](https://github.com/thieneret) ([#17198](https://github.com/community-scripts/ProxmoxVE/pull/17198))
- passwordpusher: restore data before running migrations [@MickLesk](https://github.com/MickLesk) ([#17141](https://github.com/community-scripts/ProxmoxVE/pull/17141))
- paperclip: install the rust toolchain needed by the runner build [@MickLesk](https://github.com/MickLesk) ([#17142](https://github.com/community-scripts/ProxmoxVE/pull/17142))
- homepage: run next directly instead of through pnpm [@MickLesk](https://github.com/MickLesk) ([#17155](https://github.com/community-scripts/ProxmoxVE/pull/17155))
- changedetection: fix: pin browserless [@CrazyWolf13](https://github.com/CrazyWolf13) ([#17163](https://github.com/community-scripts/ProxmoxVE/pull/17163))
### 💾 Core
- #### 🐞 Bug Fixes
- core.func: fall back to a usable HOME when the shell has none [@MickLesk](https://github.com/MickLesk) ([#17154](https://github.com/community-scripts/ProxmoxVE/pull/17154))
### 🧰 Tools
- Dockhand ([#17191](https://github.com/community-scripts/ProxmoxVE/pull/17191))
- #### 🐞 Bug Fixes
- update-apps: rewrite the retired Gitea base in every container before updating it [@MickLesk](https://github.com/MickLesk) ([#17156](https://github.com/community-scripts/ProxmoxVE/pull/17156))
- #### 🔧 Refactor
- Rename lxc-delete.sh to guest-delete.sh [@MickLesk](https://github.com/MickLesk) ([#17152](https://github.com/community-scripts/ProxmoxVE/pull/17152))
### 📚 Documentation
- issue template: add PVE release, execution context and phase; refresh distro list / pve versions [@MickLesk](https://github.com/MickLesk) ([#17160](https://github.com/community-scripts/ProxmoxVE/pull/17160))
## 2026-09-10
### 🆕 New Scripts
- Chevereto ([#17131](https://github.com/community-scripts/ProxmoxVE/pull/17131))
- Portabase ([#17111](https://github.com/community-scripts/ProxmoxVE/pull/17111))
- Logseq ([#17112](https://github.com/community-scripts/ProxmoxVE/pull/17112))
- Safebucket ([#17096](https://github.com/community-scripts/ProxmoxVE/pull/17096))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Immich v3.2.0 [@vhsdream](https://github.com/vhsdream) ([#17137](https://github.com/community-scripts/ProxmoxVE/pull/17137))
- fix(solidtime): prevent composer install from hanging on root prompt [@supersoju](https://github.com/supersoju) ([#17146](https://github.com/community-scripts/ProxmoxVE/pull/17146))
- fix(hermesagent): wait for root gateway cleanup [@steveonjava](https://github.com/steveonjava) ([#17147](https://github.com/community-scripts/ProxmoxVE/pull/17147))
### 💾 Core
- Keep the script name when regenerating the entrypoint [@MickLesk](https://github.com/MickLesk) ([core#35](https://github.com/community-scripts/core/pull/35))
- Rewrite the dead Gitea base onto GitHub instead of failing the update [@MickLesk](https://github.com/MickLesk) ([core#33](https://github.com/community-scripts/core/pull/33))
- core.func: fall back to a usable HOME when the shell has none [@MickLesk](https://github.com/MickLesk) ([core#32](https://github.com/community-scripts/core/pull/32))
## 2026-09-09
### 🆕 New Scripts
- Lingarr ([#17130](https://github.com/community-scripts/ProxmoxVE/pull/17130))
### 🚀 Updated Scripts
- vm: drop the discussions link from the summary [@MickLesk](https://github.com/MickLesk) ([#17117](https://github.com/community-scripts/ProxmoxVE/pull/17117))
- #### 🐞 Bug Fixes
- fix(hermesagent): stop spurious root gateway after update [@steveonjava](https://github.com/steveonjava) ([#17126](https://github.com/community-scripts/ProxmoxVE/pull/17126))
## 2026-09-08
### 🆕 New Scripts
- Decypharr ([#17108](https://github.com/community-scripts/ProxmoxVE/pull/17108))
- Stash ([#17106](https://github.com/community-scripts/ProxmoxVE/pull/17106))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Update Jellyfin FFmpeg dependency to version 8 [@MickLesk](https://github.com/MickLesk) ([#17109](https://github.com/community-scripts/ProxmoxVE/pull/17109))
### 💾 Core
- Treat a cut-short forge response as a failure, not as HTTP 200 [@MickLesk](https://github.com/MickLesk) ([core#31](https://github.com/community-scripts/core/pull/31))
- Generate app headers [@github-actions[bot]](https://github.com/github-actions[bot]) ([core#28](https://github.com/community-scripts/core/pull/28))
- cloud-init: drop the "configure in Proxmox UI" hint [@MickLesk](https://github.com/MickLesk) ([core#30](https://github.com/community-scripts/core/pull/30))
- Survive an empty /usr/bin/update instead of aborting the run [@MickLesk](https://github.com/MickLesk) ([core#29](https://github.com/community-scripts/core/pull/29))
## 2026-09-07
### 🆕 New Scripts
- Chatwoot ([#17095](https://github.com/community-scripts/ProxmoxVE/pull/17095))
- whisparr-eros ([#17094](https://github.com/community-scripts/ProxmoxVE/pull/17094))
- Matter-Hub ([#17093](https://github.com/community-scripts/ProxmoxVE/pull/17093))
- Journiv ([#17092](https://github.com/community-scripts/ProxmoxVE/pull/17092))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- kaneo: bump Node.js from 22 to 24 [@github-actions[bot]](https://github.com/github-actions[bot]) ([#17086](https://github.com/community-scripts/ProxmoxVE/pull/17086))
- iobroker: bump Node.js from 24 to 26 [@github-actions[bot]](https://github.com/github-actions[bot]) ([#17085](https://github.com/community-scripts/ProxmoxVE/pull/17085))
- reactive-resume: repair any wrong WorkingDirectory on update [@MickLesk](https://github.com/MickLesk) ([#17068](https://github.com/community-scripts/ProxmoxVE/pull/17068))
- mediamtx: keep mediamtx.yml across updates [@MickLesk](https://github.com/MickLesk) ([#17069](https://github.com/community-scripts/ProxmoxVE/pull/17069))
- omnitools: allow remote action while npm ci [@MickLesk](https://github.com/MickLesk) ([#17070](https://github.com/community-scripts/ProxmoxVE/pull/17070))
- #### ✨ New Features
- netboot-xyz: add Secure Boot and Legacy assets [@MickLesk](https://github.com/MickLesk) ([#17066](https://github.com/community-scripts/ProxmoxVE/pull/17066))
- #### 🔧 Refactor
- flatnotes: follow upstream move to uv and Python 3.13 [@MickLesk](https://github.com/MickLesk) ([#17090](https://github.com/community-scripts/ProxmoxVE/pull/17090))
- heimdall: set up PHP 8.4 on update, keep only the database, run migrations [@MickLesk](https://github.com/MickLesk) ([#17067](https://github.com/community-scripts/ProxmoxVE/pull/17067))
### 📂 Github
- github: Open per-script Node bump PRs [@MickLesk](https://github.com/MickLesk) ([#17065](https://github.com/community-scripts/ProxmoxVE/pull/17065))
## 2026-09-06
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Fix Sonarqube update script to add +x on sonar.sh [@jarihu](https://github.com/jarihu) ([#17056](https://github.com/community-scripts/ProxmoxVE/pull/17056))
## 2026-09-05 ## 2026-09-05
### 🚀 Updated Scripts ### 🚀 Updated Scripts

3
.github/pull_request_template.md generated vendored
View File

@@ -14,6 +14,9 @@ Fixes #
- [ ] **Tested thoroughly** Changes work as expected. - [ ] **Tested thoroughly** Changes work as expected.
- [ ] **No security risks** No hardcoded secrets, unnecessary privilege escalations, or permission issues. - [ ] **No security risks** No hardcoded secrets, unnecessary privilege escalations, or permission issues.
**Tested on:** <!-- e.g. PVE 9.2 / Debian 13 / fresh install + update. Write "not tested" if you could not run it. -->
--- ---
## 🤖 AI Assistance (**X** in brackets) ## 🤖 AI Assistance (**X** in brackets)

View File

@@ -101,6 +101,9 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
@@ -114,7 +117,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details> <details>
<summary><h4>September (5 entries)</h4></summary> <summary><h4>September (12 entries)</h4></summary>
[View September 2026 Changelog](.github/changelogs/2026/09.md) [View September 2026 Changelog](.github/changelogs/2026/09.md)
@@ -540,6 +543,125 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details> </details>
## 2026-09-15
### 🆕 New Scripts
- valhalla ([#17231](https://github.com/community-scripts/ProxmoxVE/pull/17231))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- tracearr: copy packages/emails into the deploy tree [@connorgallopo](https://github.com/connorgallopo) ([#17268](https://github.com/community-scripts/ProxmoxVE/pull/17268))
- Immich: Pin to v3.2.1 [@vhsdream](https://github.com/vhsdream) ([#17264](https://github.com/community-scripts/ProxmoxVE/pull/17264))
### 💾 Core
- Add vm_extract_image, which two VM scripts already call [@MickLesk](https://github.com/MickLesk) ([core#40](https://github.com/community-scripts/core/pull/40))
- Releases: rank releases on their numbers, not on sort -V over the raw tag [@MickLesk](https://github.com/MickLesk) ([core#39](https://github.com/community-scripts/core/pull/39))
### 🧰 Tools
- #### 🔧 Refactor
- Refactor: monitor-all (decide on flag values, not on key presence) [@MickLesk](https://github.com/MickLesk) ([#17261](https://github.com/community-scripts/ProxmoxVE/pull/17261))
## 2026-09-14
### 🆕 New Scripts
- Borg-UI ([#17258](https://github.com/community-scripts/ProxmoxVE/pull/17258))
### 🚀 Updated Scripts
- SparkyFitness: substitute NGINX_RATE_LIMIT in nginx config [@RafBorrelli](https://github.com/RafBorrelli) ([#17256](https://github.com/community-scripts/ProxmoxVE/pull/17256))
- #### 🐞 Bug Fixes
- spliit: bump Node.js from 24 to 26 [@github-actions[bot]](https://github.com/github-actions[bot]) ([#17250](https://github.com/community-scripts/ProxmoxVE/pull/17250))
## 2026-09-13
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Downgrade iobroker to Node 24 [@Copilot](https://github.com/Copilot) ([#17229](https://github.com/community-scripts/ProxmoxVE/pull/17229))
### 💾 Core
- Pick the highest release version, not the newest published one [@MickLesk](https://github.com/MickLesk) ([core#38](https://github.com/community-scripts/core/pull/38))
## 2026-09-12
### 🆕 New Scripts
- Elasticsearch ([#17188](https://github.com/community-scripts/ProxmoxVE/pull/17188))
- Hammer ([#17189](https://github.com/community-scripts/ProxmoxVE/pull/17189))
- gotenberg ([#17205](https://github.com/community-scripts/ProxmoxVE/pull/17205))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix(dispatcharr): add comskip installation and build dependencies [@eXistC](https://github.com/eXistC) ([#16224](https://github.com/community-scripts/ProxmoxVE/pull/16224))
- poznote: serve from src/public docroot [@MickLesk](https://github.com/MickLesk) ([#17187](https://github.com/community-scripts/ProxmoxVE/pull/17187))
- calibre-web: use calibreweb release identifier to avoid version file collision [@MickLesk](https://github.com/MickLesk) ([#17186](https://github.com/community-scripts/ProxmoxVE/pull/17186))
- #### ✨ New Features
- Docker VM: Feature Bump - Refactor script for improved functionality [@MickLesk](https://github.com/MickLesk) ([#17216](https://github.com/community-scripts/ProxmoxVE/pull/17216))
- feat(jitsi-meet): optional public setup (FQDN, Let's Encrypt, NAT, secure domain) [@klanghans](https://github.com/klanghans) ([#17132](https://github.com/community-scripts/ProxmoxVE/pull/17132))
- #### 🔧 Refactor
- Paperless-NGX: add --no-sync to uv run services [@MickLesk](https://github.com/MickLesk) ([#17210](https://github.com/community-scripts/ProxmoxVE/pull/17210))
### 💾 Core
- VM's: show the selected CPU model instead of doubling it [@MickLesk](https://github.com/MickLesk) ([core#37](https://github.com/community-scripts/core/pull/37))
- Generate app headers [@github-actions[bot]](https://github.com/github-actions[bot]) ([core#36](https://github.com/community-scripts/core/pull/36))
## 2026-09-11
### 🆕 New Scripts
- Lemonade-Server ([#17190](https://github.com/community-scripts/ProxmoxVE/pull/17190))
- OneTimeSecret ([#17097](https://github.com/community-scripts/ProxmoxVE/pull/17097))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- update authentik to 2026.8.2 [@thieneret](https://github.com/thieneret) ([#17198](https://github.com/community-scripts/ProxmoxVE/pull/17198))
- passwordpusher: restore data before running migrations [@MickLesk](https://github.com/MickLesk) ([#17141](https://github.com/community-scripts/ProxmoxVE/pull/17141))
- paperclip: install the rust toolchain needed by the runner build [@MickLesk](https://github.com/MickLesk) ([#17142](https://github.com/community-scripts/ProxmoxVE/pull/17142))
- homepage: run next directly instead of through pnpm [@MickLesk](https://github.com/MickLesk) ([#17155](https://github.com/community-scripts/ProxmoxVE/pull/17155))
- changedetection: fix: pin browserless [@CrazyWolf13](https://github.com/CrazyWolf13) ([#17163](https://github.com/community-scripts/ProxmoxVE/pull/17163))
### 💾 Core
- #### 🐞 Bug Fixes
- core.func: fall back to a usable HOME when the shell has none [@MickLesk](https://github.com/MickLesk) ([#17154](https://github.com/community-scripts/ProxmoxVE/pull/17154))
### 🧰 Tools
- Dockhand ([#17191](https://github.com/community-scripts/ProxmoxVE/pull/17191))
- #### 🐞 Bug Fixes
- update-apps: rewrite the retired Gitea base in every container before updating it [@MickLesk](https://github.com/MickLesk) ([#17156](https://github.com/community-scripts/ProxmoxVE/pull/17156))
- #### 🔧 Refactor
- Rename lxc-delete.sh to guest-delete.sh [@MickLesk](https://github.com/MickLesk) ([#17152](https://github.com/community-scripts/ProxmoxVE/pull/17152))
### 📚 Documentation
- issue template: add PVE release, execution context and phase; refresh distro list / pve versions [@MickLesk](https://github.com/MickLesk) ([#17160](https://github.com/community-scripts/ProxmoxVE/pull/17160))
## 2026-09-10 ## 2026-09-10
### 🆕 New Scripts ### 🆕 New Scripts
@@ -1118,142 +1240,3 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- Refactor: PowerDNS move poweradmin database outside the web root [@MickLesk](https://github.com/MickLesk) ([#16476](https://github.com/community-scripts/ProxmoxVE/pull/16476)) - Refactor: PowerDNS move poweradmin database outside the web root [@MickLesk](https://github.com/MickLesk) ([#16476](https://github.com/community-scripts/ProxmoxVE/pull/16476))
- paperless-ngx: run services with uv --no-sync to avoid startup network dependency [@MickLesk](https://github.com/MickLesk) ([#16479](https://github.com/community-scripts/ProxmoxVE/pull/16479)) - paperless-ngx: run services with uv --no-sync to avoid startup network dependency [@MickLesk](https://github.com/MickLesk) ([#16479](https://github.com/community-scripts/ProxmoxVE/pull/16479))
## 2026-08-13
### 🆕 New Scripts
- SuggestArr ([#16449](https://github.com/community-scripts/ProxmoxVE/pull/16449))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix(stirling-pdf): LibreOffice listener collides with unoserver on UNO port 2002, burning a core [@angusmaul](https://github.com/angusmaul) ([#16460](https://github.com/community-scripts/ProxmoxVE/pull/16460))
- fix(reitti): enable SNI for tile cache [@kylemd](https://github.com/kylemd) ([#16463](https://github.com/community-scripts/ProxmoxVE/pull/16463))
- [wanderer] refactor [@johanngrobe](https://github.com/johanngrobe) ([#16448](https://github.com/community-scripts/ProxmoxVE/pull/16448))
- #### ✨ New Features
- feat: Update koillection-install.sh to support API usage [@Crazy-Duck](https://github.com/Crazy-Duck) ([#16425](https://github.com/community-scripts/ProxmoxVE/pull/16425))
## 2026-08-12
### 🆕 New Scripts
- Stalwart ([#16388](https://github.com/community-scripts/ProxmoxVE/pull/16388))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- networkoptimizer: mitigate dotnet publish hang in LXC [@MickLesk](https://github.com/MickLesk) ([#16436](https://github.com/community-scripts/ProxmoxVE/pull/16436))
- lazylibrarian: reinstall deps after git pull on update [@MickLesk](https://github.com/MickLesk) ([#16435](https://github.com/community-scripts/ProxmoxVE/pull/16435))
- wanderer: fix deprecated meilisearch upgrade flag [@MickLesk](https://github.com/MickLesk) ([#16434](https://github.com/community-scripts/ProxmoxVE/pull/16434))
- calibre-web: fix release asset filename pattern [@MickLesk](https://github.com/MickLesk) ([#16433](https://github.com/community-scripts/ProxmoxVE/pull/16433))
- fix(stirling-pdf): unoserver installed into the venv, and login mode truncates .env [@angusmaul](https://github.com/angusmaul) ([#16439](https://github.com/community-scripts/ProxmoxVE/pull/16439))
- fix(pulse): keep the container recoverable when an update fails [@rcourtman](https://github.com/rcourtman) ([#16311](https://github.com/community-scripts/ProxmoxVE/pull/16311))
- #### 🔧 Refactor
- ConvertX: add some new dependencies [@MickLesk](https://github.com/MickLesk) ([#16437](https://github.com/community-scripts/ProxmoxVE/pull/16437))
## 2026-08-11
### 🚀 Updated Scripts
- Update source URL for Reactive Resume [@MickLesk](https://github.com/MickLesk) ([#16407](https://github.com/community-scripts/ProxmoxVE/pull/16407))
- #### 🐞 Bug Fixes
- Pelican-Panel: add php artisan p:environment:database [@MickLesk](https://github.com/MickLesk) ([#16397](https://github.com/community-scripts/ProxmoxVE/pull/16397))
- outline: fix URL sed matching wrong line in .env.sample // refactor .env generation [@MickLesk](https://github.com/MickLesk) ([#16408](https://github.com/community-scripts/ProxmoxVE/pull/16408))
- paperless-ngx: reindex Tantivy search index on webserver start [@MickLesk](https://github.com/MickLesk) ([#16395](https://github.com/community-scripts/ProxmoxVE/pull/16395))
- karakeep: pin Node.js to 22 LTS, avoid Node 24.19 better-sqlite3 crash [@MickLesk](https://github.com/MickLesk) ([#16396](https://github.com/community-scripts/ProxmoxVE/pull/16396))
- #### ✨ New Features
- Open WebUI: add optional OpenTelemetry package install [@irishpadres](https://github.com/irishpadres) ([#16415](https://github.com/community-scripts/ProxmoxVE/pull/16415))
### 🧰 Tools
- #### 🐞 Bug Fixes
- fix(add-tailscale-lxc): stop spinner before whiptail menu [@halcycon](https://github.com/halcycon) ([#16402](https://github.com/community-scripts/ProxmoxVE/pull/16402))
- #### 🔧 Refactor
- arcane: fix projects/builds dir ownership for non-root container UID [@MickLesk](https://github.com/MickLesk) ([#16411](https://github.com/community-scripts/ProxmoxVE/pull/16411))
## 2026-08-10
### 🆕 New Scripts
- GitLab ([#16386](https://github.com/community-scripts/ProxmoxVE/pull/16386))
- TeslaMate ([#16385](https://github.com/community-scripts/ProxmoxVE/pull/16385))
- tor-snowflake ([#15684](https://github.com/community-scripts/ProxmoxVE/pull/15684))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- ErsatzTV: update ffmpeg to 8.1 version [@MickLesk](https://github.com/MickLesk) ([#16383](https://github.com/community-scripts/ProxmoxVE/pull/16383))
### 🧰 Tools
- post-pdm-install ([#16368](https://github.com/community-scripts/ProxmoxVE/pull/16368))
## 2026-08-09
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Fix: CouchDB Erlang cookie breaks vm.args (use hex) [@fudianchn](https://github.com/fudianchn) ([#16361](https://github.com/community-scripts/ProxmoxVE/pull/16361))
- SparkyFitness: Install Git for frontend builds [@MickLesk](https://github.com/MickLesk) ([#16352](https://github.com/community-scripts/ProxmoxVE/pull/16352))
- Byparr: Use invisible-playwright browser setup [@MickLesk](https://github.com/MickLesk) ([#16353](https://github.com/community-scripts/ProxmoxVE/pull/16353))
- Crafty Controller: Restore ownership after updates [@MickLesk](https://github.com/MickLesk) ([#16354](https://github.com/community-scripts/ProxmoxVE/pull/16354))
- Webtrees: Fix schema check in silent mode [@MickLesk](https://github.com/MickLesk) ([#16355](https://github.com/community-scripts/ProxmoxVE/pull/16355))
- SigNoz: Allow legacy metadata schema on ClickHouse 26 [@MickLesk](https://github.com/MickLesk) ([#16356](https://github.com/community-scripts/ProxmoxVE/pull/16356))
### 🧰 Tools
- #### ✨ New Features
- Portainer: Update existing CE and BE installations [@MickLesk](https://github.com/MickLesk) ([#16357](https://github.com/community-scripts/ProxmoxVE/pull/16357))
### 📚 Documentation
- github: update Star History links and image sources [@MickLesk](https://github.com/MickLesk) ([#16367](https://github.com/community-scripts/ProxmoxVE/pull/16367))
## 2026-08-08
### 🆕 New Scripts
- Ignis ([#16330](https://github.com/community-scripts/ProxmoxVE/pull/16330))
### 💾 Core
- #### ✨ New Features
- core - setup_nodejs: bypass npm allowScripts policy globally on npm >=11 [@MickLesk](https://github.com/MickLesk) ([#16280](https://github.com/community-scripts/ProxmoxVE/pull/16280))
## 2026-08-07
### 🆕 New Scripts
- NetworkOptimizer ([#16328](https://github.com/community-scripts/ProxmoxVE/pull/16328))
- Orb ([#16329](https://github.com/community-scripts/ProxmoxVE/pull/16329))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- HortusFox: start applying db migrations [@tomfrenzel](https://github.com/tomfrenzel) ([#16324](https://github.com/community-scripts/ProxmoxVE/pull/16324))
- Docker: report container updates instead of prompting, stop auto-updating Portainer Agent, fix addon detection of legacy Portainer [@MickLesk](https://github.com/MickLesk) ([#16298](https://github.com/community-scripts/ProxmoxVE/pull/16298))
- Immich: retry mise install on transient npm download failures [@MickLesk](https://github.com/MickLesk) ([#16301](https://github.com/community-scripts/ProxmoxVE/pull/16301))
- changedetection: remove msttcorefonts to fix install hang [@austinpilz](https://github.com/austinpilz) ([#16319](https://github.com/community-scripts/ProxmoxVE/pull/16319))
- #### 🔧 Refactor
- core: extend new vars and pocketbase values [@MickLesk](https://github.com/MickLesk) ([#16313](https://github.com/community-scripts/ProxmoxVE/pull/16313))

View File

@@ -49,7 +49,7 @@ function update_script() {
RUST_PROFILE="minimal" RUST_TOOLCHAIN="stable" setup_rust RUST_PROFILE="minimal" RUST_TOOLCHAIN="stable" setup_rust
setup_yq setup_yq
AUTHENTIK_VERSION="version/2026.8.1" AUTHENTIK_VERSION="version/2026.8.2"
# Source: https://github.com/goauthentik/fips/blob/main/Makefile#L26 # Source: https://github.com/goauthentik/fips/blob/main/Makefile#L26
XMLSEC_VERSION="1.3.12" XMLSEC_VERSION="1.3.12"
@@ -184,8 +184,12 @@ EOF
msg_info "Updating services" msg_info "Updating services"
sed -i 's/authentik Go Server (API Gateway)/authentik Server/g' /etc/systemd/system/authentik-server.service sed -i 's/authentik Go Server (API Gateway)/authentik Server/g' /etc/systemd/system/authentik-server.service
sed -i '/ExecStart=/i ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-server.service if ! grep -qF -- 'ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-server.service; then
sed -i '/ExecStart=/i ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-worker.service sed -i '/ExecStart=/i ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-server.service
fi
if ! grep -qF -- 'ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-worker.service; then
sed -i '/ExecStart=/i ExecStartPre=/usr/bin/mkdir -p "${TMPDIR}"' /etc/systemd/system/authentik-worker.service
fi
systemctl daemon-reload systemctl daemon-reload
msg_ok "Updated services" msg_ok "Updated services"
@@ -224,8 +228,8 @@ for i in {1..10}; do
sleep 1 sleep 1
done done
$STD pct exec "$CTID" -- bash -c "mkdir -p /opt/authentik-data/{certs,media,geoip,templates}; \ $STD pct exec "$CTID" -- bash -c "mkdir -p /opt/authentik-data/{certs,media,geoip,templates}; \
cp /opt/authentik/tests/GeoLite2-ASN-Test.mmdb /opt/authentik-data/geoip/GeoLite2-ASN.mmdb; \ cp /opt/authentik/tests/geoip/GeoLite2-ASN-Test.mmdb /opt/authentik-data/geoip/GeoLite2-ASN.mmdb; \
cp /opt/authentik/tests/GeoLite2-City-Test.mmdb /opt/authentik-data/geoip/GeoLite2-City.mmdb; \ cp /opt/authentik/tests/geoip/GeoLite2-City-Test.mmdb /opt/authentik-data/geoip/GeoLite2-City.mmdb; \
cp -r /opt/authentik/blueprints /opt/authentik-data/; \ cp -r /opt/authentik/blueprints /opt/authentik-data/; \
rm -r /opt/authentik/blueprints; \ rm -r /opt/authentik/blueprints; \
find /opt/authentik-data -path '*/lost+found' -prune -o -exec chown authentik:authentik {} +" find /opt/authentik-data -path '*/lost+found' -prune -o -exec chown authentik:authentik {} +"

121
ct/borg-ui.sh Normal file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/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/karanhudia/borg-ui
APP="Borg-UI"
var_tags="${var_tags:-backup}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
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/borg-ui ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "borg-ui" "karanhudia/borg-ui"; then
msg_info "Stopping Service"
systemctl stop borg-ui
msg_ok "Stopped Service"
create_backup /opt/borg-ui/.env
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "borg-ui" "karanhudia/borg-ui" "tarball"
restore_backup
BORG_UI_VERSION=$(cat "$HOME/.borg-ui" 2>/dev/null)
if [[ -n "$BORG_UI_VERSION" ]]; then
if grep -q '^APP_VERSION=' /opt/borg-ui/.env; then
sed -i "s|^APP_VERSION=.*|APP_VERSION=${BORG_UI_VERSION}|" /opt/borg-ui/.env
else
echo "APP_VERSION=${BORG_UI_VERSION}" >>/opt/borg-ui/.env
fi
fi
# Only the three Borg pins appear in every release of this file; PYTHON_VERSION
# and RCLONE_VERSION were added upstream after v2.2.6, so both fall back.
RUNTIME_ENV="/opt/borg-ui/docker/runtime-base.env"
BORG1_VERSION=$(sed -n 's/^BORG1_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG2_VERSION=$(sed -n 's/^BORG2_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORGSTORE_VERSION=$(sed -n 's/^BORGSTORE_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
RCLONE_VERSION=$(sed -n 's/^RCLONE_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG_PYTHON=$(sed -n 's/^PYTHON_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG_PYTHON="${BORG_PYTHON:-3.12}"
if [[ -z "$BORG1_VERSION" || -z "$BORG2_VERSION" || -z "$BORGSTORE_VERSION" ]]; then
msg_error "Could not read the pinned Borg versions from ${RUNTIME_ENV}"
exit 1
fi
if [[ "$(cat /opt/borg1-venv/.pinned_version 2>/dev/null)" != "$BORG1_VERSION" ]]; then
msg_info "Installing Borg ${BORG1_VERSION} (Patience)"
$STD uv venv --python "$BORG_PYTHON" /opt/borg1-venv
$STD uv pip install --python /opt/borg1-venv pyfuse3 "borgbackup==${BORG1_VERSION}"
echo "$BORG1_VERSION" >/opt/borg1-venv/.pinned_version
ln -sf /opt/borg1-venv/bin/borg /usr/local/bin/borg
msg_ok "Installed Borg ${BORG1_VERSION}"
fi
if [[ "$(cat /opt/borg2-venv/.pinned_version 2>/dev/null)" != "${BORG2_VERSION}-${BORGSTORE_VERSION}" ]]; then
msg_info "Installing Borg ${BORG2_VERSION} (Patience)"
$STD uv venv --python "$BORG_PYTHON" /opt/borg2-venv
$STD uv pip install --python /opt/borg2-venv pyfuse3 "borgbackup==${BORG2_VERSION}" "borgstore[rclone,sftp,rest,s3,blake3]==${BORGSTORE_VERSION}"
echo "${BORG2_VERSION}-${BORGSTORE_VERSION}" >/opt/borg2-venv/.pinned_version
ln -sf /opt/borg2-venv/bin/borg /usr/local/bin/borg2
msg_ok "Installed Borg ${BORG2_VERSION}"
fi
RCLONE_TAG="${RCLONE_VERSION:+v${RCLONE_VERSION}}"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "rclone" "rclone/rclone" "prebuild" "${RCLONE_TAG:-latest}" "/opt/rclone" "rclone-${RCLONE_TAG:-*}-linux-$(arch_resolve amd64 arm64).zip"
ln -sf /opt/rclone/rclone /usr/local/bin/rclone
msg_info "Building Frontend"
cd /opt/borg-ui/frontend
$STD npm ci
$STD npm run build
rm -rf /opt/borg-ui/app/static
mkdir -p /opt/borg-ui/app/static
cp -r /opt/borg-ui/frontend/build/* /opt/borg-ui/app/static/
msg_ok "Built Frontend"
msg_info "Updating Python Environment"
cd /opt/borg-ui
$STD uv venv --python "$BORG_PYTHON" /opt/borg-ui/.venv
$STD uv pip install --python /opt/borg-ui/.venv -r requirements.txt
msg_ok "Updated Python Environment"
msg_info "Starting Service"
systemctl start borg-ui
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 "${GATEWAY}${BGN}http://${IP}:8081${CL}"

View File

@@ -32,14 +32,18 @@ function update_script() {
exit exit
fi fi
if check_for_gh_release "Calibre-Web" "janeczku/calibre-web"; then if [[ -f /root/.calibre-web && ! -e /root/.calibreweb ]]; then
mv /root/.calibre-web /root/.calibreweb
fi
if check_for_gh_release "calibreweb" "janeczku/calibre-web"; then
msg_info "Stopping Service" msg_info "Stopping Service"
systemctl stop calibre-web systemctl stop calibre-web
msg_ok "Stopped Service" msg_ok "Stopped Service"
create_backup /opt/calibre-web/data create_backup /opt/calibre-web/data
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Calibre-Web" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibreweb*.tar.gz" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "calibreweb" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibreweb*.tar.gz"
setup_uv setup_uv
msg_info "Installing Dependencies" msg_info "Installing Dependencies"

View File

@@ -69,6 +69,7 @@ function update_script() {
$STD git -C /opt/browserless/ reset --hard origin/main $STD git -C /opt/browserless/ reset --hard origin/main
$STD npm update --prefix /opt/browserless $STD npm update --prefix /opt/browserless
$STD npm ci --include=optional --include=dev --prefix /opt/browserless $STD npm ci --include=optional --include=dev --prefix /opt/browserless
$STD npm install --save-exact playwright-core@1.62.1 --prefix /opt/browserless
$STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps $STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps
# Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed. # Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed.
$STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome $STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome

View File

@@ -106,7 +106,18 @@ EOF
msg_ok "Migrated Nginx Configuration" msg_ok "Migrated Nginx Configuration"
fi fi
ensure_dependencies vlc-bin vlc-plugin-base ensure_dependencies vlc-bin vlc-plugin-base build-essential autoconf libtool libargtable2-dev libavformat-dev libsdl2-dev libswscale-dev
if ! command -v comskip &> /dev/null; then
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Comskip" "erikkaashoek/Comskip" "tarball"
msg_info "Compiling Comskip"
cd /opt/Comskip
$STD ./autogen.sh
$STD ./configure
$STD make
$STD make install
msg_ok "Compiled and Installed Comskip"
fi
if check_for_gh_release "Dispatcharr" "Dispatcharr/Dispatcharr"; then if check_for_gh_release "Dispatcharr" "Dispatcharr/Dispatcharr"; then
msg_info "Stopping Services" msg_info "Stopping Services"

56
ct/elasticsearch.sh Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/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://www.elastic.co/elasticsearch
APP="Elasticsearch"
var_tags="${var_tags:-database;search}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-20}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_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 [[ ! -f /etc/elasticsearch/elasticsearch.yml ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ${APP}"
$STD apt update
$STD apt install -y elasticsearch
msg_ok "Updated ${APP}"
msg_info "Restarting Service"
systemctl restart elasticsearch
msg_ok "Restarted 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 "${GATEWAY}${BGN}http://${IP}:9200${CL}"
echo -e "${INFO}${YW}Set the password for the 'elastic' user:${CL}"
echo -e "${TAB}${DEFAULT}${BGN}/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic${CL}"

75
ct/gotenberg.sh Normal file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/gotenberg/gotenberg
APP="Gotenberg"
var_tags="${var_tags:-document;pdf}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-15}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
#var_arm64="${var_arm64:-no}" # unset = ask the user; set yes/no only when verified
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/gotenberg.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "gotenberg" "gotenberg/gotenberg"; then
msg_info "Stopping Service"
systemctl stop gotenberg
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gotenberg" "gotenberg/gotenberg" "tarball" "latest" "/opt/gotenberg"
GO_VERSION="$(awk '$1=="go"{print $2}' /opt/gotenberg/go.mod | cut -d. -f1,2)" setup_go
msg_info "Building gotenberg (Patience)"
cd /opt/gotenberg
export CGO_ENABLED=0
$STD go mod download
$STD go build -o /usr/local/bin/gotenberg \
-ldflags "-s -w -X 'github.com/gotenberg/gotenberg/v8/cmd.Version=$(cat ~/.gotenberg)'" \
cmd/gotenberg/main.go
msg_ok "Built gotenberg"
msg_info "Updating unoconverter"
UNOCONVERTER_VERSION=$(get_latest_github_release "gotenberg/unoconverter" "false")
download_file "https://raw.githubusercontent.com/gotenberg/unoconverter/${UNOCONVERTER_VERSION}/unoconv" /usr/local/bin/unoconverter
chmod +x /usr/local/bin/unoconverter
msg_ok "Updated unoconverter"
msg_info "Starting Service"
systemctl start gotenberg
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}Gotenberg is a stateless API and has no web interface.${CL}"
echo -e "${INFO}${YW}Check the health endpoint using the following URL:${CL}"
echo -e "${GATEWAY}${BGN}http://${IP}:3000/health${CL}"

58
ct/hammer.sh Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/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/Darkrock-Studios/hammer-editor
APP="Hammer"
var_tags="${var_tags:-writing;sync-server}"
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_unprivileged="${var_unprivileged:-1}"
var_arm64="${var_arm64:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /opt/hammer ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "hammer" "Darkrock-Studios/hammer-editor"; then
msg_info "Stopping Service"
systemctl stop hammer
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "hammer" "Darkrock-Studios/hammer-editor" "prebuild" "latest" "/opt/hammer" "server.zip"
chmod +x /opt/hammer/bin/server
msg_info "Starting Service"
systemctl start hammer
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 "${GATEWAY}${BGN}http://${IP}:8080${CL}"

6
ct/headers/borg-ui Normal file
View File

@@ -0,0 +1,6 @@
____ __ ______
/ __ )____ _________ _ / / / / _/
/ __ / __ \/ ___/ __ `/_____/ / / // /
/ /_/ / /_/ / / / /_/ /_____/ /_/ // /
/_____/\____/_/ \__, / \____/___/
/____/

6
ct/headers/elasticsearch Normal file
View File

@@ -0,0 +1,6 @@
________ __ _ __
/ ____/ /___ ______/ /_(_)____________ ____ ___________/ /_
/ __/ / / __ `/ ___/ __/ / ___/ ___/ _ \/ __ `/ ___/ ___/ __ \
/ /___/ / /_/ (__ ) /_/ / /__(__ ) __/ /_/ / / / /__/ / / /
/_____/_/\__,_/____/\__/_/\___/____/\___/\__,_/_/ \___/_/ /_/

6
ct/headers/gotenberg Normal file
View File

@@ -0,0 +1,6 @@
______ __ __
/ ____/___ / /____ ____ / /_ ___ _________ _
/ / __/ __ \/ __/ _ \/ __ \/ __ \/ _ \/ ___/ __ `/
/ /_/ / /_/ / /_/ __/ / / / /_/ / __/ / / /_/ /
\____/\____/\__/\___/_/ /_/_.___/\___/_/ \__, /
/____/

6
ct/headers/hammer Normal file
View File

@@ -0,0 +1,6 @@
__ __
/ / / /___ _____ ___ ____ ___ ___ _____
/ /_/ / __ `/ __ `__ \/ __ `__ \/ _ \/ ___/
/ __ / /_/ / / / / / / / / / / / __/ /
/_/ /_/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_/

View File

@@ -0,0 +1,6 @@
__ __ _____
/ / ___ ____ ___ ____ ____ ____ _____/ /__ / ___/___ ______ _____ _____
/ / / _ \/ __ `__ \/ __ \/ __ \/ __ `/ __ / _ \______\__ \/ _ \/ ___/ | / / _ \/ ___/
/ /___/ __/ / / / / / /_/ / / / / /_/ / /_/ / __/_____/__/ / __/ / | |/ / __/ /
/_____/\___/_/ /_/ /_/\____/_/ /_/\__,_/\__,_/\___/ /____/\___/_/ |___/\___/_/

6
ct/headers/onetimesecret Normal file
View File

@@ -0,0 +1,6 @@
____ _______ _____ __
/ __ \____ ___/_ __(_)___ ___ ___ / ___/___ _____________ / /_
/ / / / __ \/ _ \/ / / / __ `__ \/ _ \\__ \/ _ \/ ___/ ___/ _ \/ __/
/ /_/ / / / / __/ / / / / / / / / __/__/ / __/ /__/ / / __/ /_
\____/_/ /_/\___/_/ /_/_/ /_/ /_/\___/____/\___/\___/_/ \___/\__/

6
ct/headers/valhalla Normal file
View File

@@ -0,0 +1,6 @@
_ __ ____ ____
| | / /___ _/ / /_ ____ _/ / /___ _
| | / / __ `/ / __ \/ __ `/ / / __ `/
| |/ / /_/ / / / / / /_/ / / / /_/ /
|___/\__,_/_/_/ /_/\__,_/_/_/\__,_/

View File

@@ -83,6 +83,10 @@ EOF
sed -i '/^ExecStart=/i Environment=CI=true' /etc/systemd/system/homepage.service sed -i '/^ExecStart=/i Environment=CI=true' /etc/systemd/system/homepage.service
systemctl daemon-reload systemctl daemon-reload
fi fi
if grep -q '^ExecStart=pnpm start' /etc/systemd/system/homepage.service; then
sed -i 's|^ExecStart=pnpm start$|ExecStart=/opt/homepage/node_modules/.bin/next start|' /etc/systemd/system/homepage.service
systemctl daemon-reload
fi
msg_ok "Updated Homepage" msg_ok "Updated Homepage"
msg_info "Starting service" msg_info "Starting service"

View File

@@ -112,7 +112,7 @@ EOF
msg_ok "Image-processing libraries up to date" msg_ok "Image-processing libraries up to date"
fi fi
RELEASE="v3.2.0" RELEASE="v3.2.1"
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"

View File

@@ -31,7 +31,7 @@ function update_script() {
exit exit
fi fi
NODE_VERSION="26" NPM_VERSION="11" setup_nodejs NODE_VERSION="24" NPM_VERSION="11" setup_nodejs
msg_info "Updating ${APP} LXC" msg_info "Updating ${APP} LXC"
$STD apt update $STD apt update

View File

@@ -17,6 +17,14 @@ var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}" var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}" var_unprivileged="${var_unprivileged:-1}"
# Optional public setup, read by the install script (all empty = LAN-only install as before).
# Without the export they never reach the container.
export var_jitsi_domain="${var_jitsi_domain:-}"
export var_jitsi_le_email="${var_jitsi_le_email:-}"
export var_jitsi_public_ip="${var_jitsi_public_ip:-}"
export var_jitsi_admin_user="${var_jitsi_admin_user:-}"
export var_jitsi_admin_pass="${var_jitsi_admin_pass:-}"
header_info "$APP" header_info "$APP"
variables variables
color color
@@ -50,4 +58,7 @@ description
msg_ok "Completed Successfully!\n" msg_ok "Completed Successfully!\n"
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
echo -e "${INFO}${YW}Access it using the following URL:${CL}" echo -e "${INFO}${YW}Access it using the following URL:${CL}"
echo -e "${GATEWAY}${BGN}https://${IP}${CL}" echo -e "${GATEWAY}${BGN}https://${var_jitsi_domain:-$IP}${CL}"
if [[ -n "${var_jitsi_domain}" ]]; then
echo -e "${INFO}${YW}Forward TCP 80/443 and UDP 10000 to the container. Secure-domain credentials (if enabled) are in ~/jitsi-meet.creds inside the container.${CL}"
fi

57
ct/lemonade-server.sh Normal file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Jamie (jamiej)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/lemonade-sdk/lemonade
APP="Lemonade-Server"
var_tags="${var_tags:-ai}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_disk="${var_disk:-80}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
var_gpu="${var_gpu:-yes}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if ! command -v lemonade &>/dev/null; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "lemonade-server" "lemonade-sdk/lemonade"; then
msg_info "Stopping Service"
systemctl stop lemond
msg_ok "Stopped Service"
fetch_and_deploy_gh_release "lemonade-server" "lemonade-sdk/lemonade" "binary" "latest" "/tmp" "lemonade-server_*-debian13_$(arch_resolve).deb"
msg_info "Starting Service"
systemctl start lemond
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 "${GATEWAY}${BGN}http://${IP}:13305${CL}"

101
ct/onetimesecret.sh Normal file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Hai Tran (epiHATR)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://onetimesecret.com/ | Github: https://github.com/onetimesecret/onetimesecret
APP="OneTimeSecret"
var_tags="${var_tags:-security;privacy;secrets}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
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
SSL_VALUE="${OTS_SSL:-}"
if [[ -n "${SSL_VALUE}" ]]; then
case "${SSL_VALUE,,}" in
1 | true | yes | on) SSL_VALUE="true" ;;
0 | false | no | off) SSL_VALUE="false" ;;
*)
msg_error "Invalid OTS_SSL value '${OTS_SSL}' (use true/false)"
exit 1
;;
esac
fi
if [[ ! -d /opt/onetimesecret ]] || [[ ! -f /opt/onetimesecret/.env ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "onetimesecret" "onetimesecret/onetimesecret"; then
msg_info "Stopping Service"
systemctl stop onetimesecret
msg_ok "Stopped Service"
create_backup /opt/onetimesecret/.env
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "onetimesecret" "onetimesecret/onetimesecret" "tarball"
RUBY_VERSION=$(tr -d ' \n' </opt/onetimesecret/.ruby-version 2>/dev/null)
RUBY_VERSION="${RUBY_VERSION:-3.4.10}" setup_ruby
PNPM_VERSION=$(sed -n 's/.*"packageManager": "pnpm@\([^"]*\)".*/\1/p' /opt/onetimesecret/package.json)
NODE_VERSION=$(tr -d ' \n' </opt/onetimesecret/.nvmrc 2>/dev/null)
NODE_VERSION="${NODE_VERSION:-25}" NODE_MODULE="pnpm@${PNPM_VERSION:-11.1.2}" setup_nodejs
restore_backup
msg_info "Reconciling Application"
systemctl enable -q --now redis-server
cd /opt/onetimesecret
mkdir -p tmp/pids log
$STD bash bin/setup reconcile
msg_ok "Reconciled Application"
msg_info "Building Frontend"
cd /opt/onetimesecret
$STD pnpm run build
msg_ok "Built Frontend"
msg_info "Starting Service"
systemctl start onetimesecret
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
}
start
build_container
description
DISPLAY_HOST="${OTS_HOST:-$IP}"
case "${OTS_SSL:-false,,}" in
1 | true | yes | on)
DISPLAY_SCHEME="https"
;;
*)
DISPLAY_SCHEME="http"
;;
esac
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}${DISPLAY_SCHEME}://${DISPLAY_HOST}${CL}"

View File

@@ -43,6 +43,8 @@ function update_script() {
restore_backup restore_backup
setup_rust
msg_info "Rebuilding Paperclip" msg_info "Rebuilding Paperclip"
cd /opt/paperclip-ai cd /opt/paperclip-ai
export HUSKY=0 export HUSKY=0

View File

@@ -169,9 +169,13 @@ function update_script() {
if ((BRIDGE_UPDATE == 0)); then if ((BRIDGE_UPDATE == 0)); then
sed -i 's|^ExecStart=.*|ExecStart=uv run --no-sync -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application"|' /etc/systemd/system/paperless-webserver.service sed -i 's|^ExecStart=.*|ExecStart=uv run --no-sync -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application"|' /etc/systemd/system/paperless-webserver.service
grep -q "document_index reindex" /etc/systemd/system/paperless-webserver.service || grep -q "document_index reindex" /etc/systemd/system/paperless-webserver.service ||
sed -i '/^ExecStart=/i ExecStartPre=uv run -- python manage.py document_index reindex --if-needed --no-progress-bar' /etc/systemd/system/paperless-webserver.service sed -i '/^ExecStart=/i ExecStartPre=uv run --no-sync -- python manage.py document_index reindex --if-needed --no-progress-bar' /etc/systemd/system/paperless-webserver.service
$STD systemctl daemon-reload
fi fi
for svc in consumer scheduler task-queue webserver; do
unit="/etc/systemd/system/paperless-${svc}.service"
[[ -f "$unit" ]] && sed -i 's|uv run -- |uv run --no-sync -- |g' "$unit"
done
$STD systemctl daemon-reload
cd /opt/paperless cd /opt/paperless
$STD uv sync --all-extras $STD uv sync --all-extras
cd /opt/paperless/src cd /opt/paperless/src

View File

@@ -40,6 +40,9 @@ function update_script() {
create_backup /opt/passwordpusher/storage /opt/passwordpusher/.env.production create_backup /opt/passwordpusher/storage /opt/passwordpusher/.env.production
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball"
restore_backup
RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
msg_info "Installing Gem Dependencies" msg_info "Installing Gem Dependencies"
@@ -62,8 +65,6 @@ function update_script() {
RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 $STD bundle exec rails assets:precompile RAILS_ENV=production SECRET_KEY_BASE_DUMMY=1 $STD bundle exec rails assets:precompile
msg_ok "Precompiled Assets" msg_ok "Precompiled Assets"
restore_backup
msg_info "Starting Service" msg_info "Starting Service"
systemctl start passwordpusher systemctl start passwordpusher
msg_ok "Started Service" msg_ok "Started Service"

View File

@@ -68,7 +68,7 @@ map \$uri \$poznote_coop {
server { server {
listen 8040; listen 8040;
root /var/www/html; root /var/www/html/public;
index index.php index.html; index index.php index.html;
gzip on; gzip on;
@@ -144,10 +144,12 @@ server {
} }
location ~ ^/data/users/[0-9]+/backgrounds/ { location ~ ^/data/users/[0-9]+/backgrounds/ {
root /var/www/html;
try_files \$uri =404; try_files \$uri =404;
} }
location ~ ^/data/css/[A-Za-z0-9._-]+\.css$ { location ~ ^/data/css/[A-Za-z0-9._-]+\.css$ {
root /var/www/html;
try_files \$uri =404; try_files \$uri =404;
} }

View File

@@ -67,6 +67,7 @@ function update_script() {
-e 's|${SPARKY_FITNESS_SERVER_PORT}|3010|g' \ -e 's|${SPARKY_FITNESS_SERVER_PORT}|3010|g' \
-e "s|\${SPARKY_FITNESS_FRONTEND_URL}|${FRONTEND_URL}|g" \ -e "s|\${SPARKY_FITNESS_FRONTEND_URL}|${FRONTEND_URL}|g" \
-e 's|${NGINX_LISTEN_PORT}|80|g' \ -e 's|${NGINX_LISTEN_PORT}|80|g' \
-e 's|${NGINX_RATE_LIMIT}|5r/s|g' \
-e 's|${NGINX_ACCESS_LOG}|/var/log/nginx/sparkyfitness.access.log|g' \ -e 's|${NGINX_ACCESS_LOG}|/var/log/nginx/sparkyfitness.access.log|g' \
-e 's|${NGINX_ERROR_LOG}|/var/log/nginx/sparkyfitness.error.log|g' \ -e 's|${NGINX_ERROR_LOG}|/var/log/nginx/sparkyfitness.error.log|g' \
-e 's|root /usr/share/nginx/html;|root /var/www/sparkyfitness;|g' \ -e 's|root /usr/share/nginx/html;|root /var/www/sparkyfitness;|g' \

View File

@@ -42,7 +42,7 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "spliit" "spliit-app/spliit" "tarball" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "spliit" "spliit-app/spliit" "tarball"
restore_backup restore_backup
NODE_VERSION="24" setup_nodejs NODE_VERSION="26" setup_nodejs
msg_info "Building Application" msg_info "Building Application"
cd /opt/spliit cd /opt/spliit

View File

@@ -124,7 +124,7 @@ EOF
$STD pnpm turbo telemetry disable $STD pnpm turbo telemetry disable
$STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web $STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
rm -rf /opt/tracearr rm -rf /opt/tracearr
mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db} mkdir -p /opt/tracearr/{packages/shared,packages/emails,apps/server,apps/web,apps/server/src/db}
cp -rf package.json /opt/tracearr/ cp -rf package.json /opt/tracearr/
cp -rf pnpm-workspace.yaml /opt/tracearr/ cp -rf pnpm-workspace.yaml /opt/tracearr/
cp -rf pnpm-lock.yaml /opt/tracearr/ cp -rf pnpm-lock.yaml /opt/tracearr/
@@ -134,6 +134,8 @@ EOF
cp -rf apps/web/dist /opt/tracearr/apps/web/dist cp -rf apps/web/dist /opt/tracearr/apps/web/dist
cp -rf packages/shared/package.json /opt/tracearr/packages/shared/ cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
cp -rf packages/emails/package.json /opt/tracearr/packages/emails/
cp -rf packages/emails/dist /opt/tracearr/packages/emails/dist
cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
cp -rf data /opt/tracearr/data cp -rf data /opt/tracearr/data
mkdir -p /opt/tracearr/data/image-cache mkdir -p /opt/tracearr/data/image-cache

104
ct/valhalla.sh Normal file
View File

@@ -0,0 +1,104 @@
#!/usr/bin/env bash
_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func"
source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func")
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/valhalla/valhalla
APP="Valhalla"
var_tags="${var_tags:-mapping;routing}"
var_cpu="${var_cpu:-6}"
var_ram="${var_ram:-6144}"
var_disk="${var_disk:-24}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/valhalla.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "prime_server" "kevinkreiser/prime_server"; then
RELEASE="$CHECK_UPDATE_RELEASE"
msg_info "Stopping Service"
systemctl stop valhalla
msg_ok "Stopped Service"
msg_info "Building prime_server ${RELEASE} (Patience)"
rm -rf /tmp/prime_server
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/kevinkreiser/prime_server /tmp/prime_server
cd /tmp/prime_server
$STD ./autogen.sh
$STD ./configure
$STD make -j"$(nproc)"
$STD make install
cd /
rm -rf /tmp/prime_server
ldconfig
echo "${RELEASE#v}" >"$HOME/.prime_server"
msg_ok "Built prime_server ${RELEASE}"
msg_info "Starting Service"
systemctl start valhalla
msg_ok "Started Service"
fi
if check_for_gh_release "valhalla" "valhalla/valhalla"; then
RELEASE="$CHECK_UPDATE_RELEASE"
msg_info "Stopping Service"
systemctl stop valhalla
msg_ok "Stopped Service"
msg_info "Fetching Valhalla ${RELEASE} (Patience)"
rm -rf /opt/valhalla
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/valhalla/valhalla.git /opt/valhalla
msg_ok "Fetched Valhalla ${RELEASE}"
msg_info "Compiling Valhalla ${RELEASE} (this takes 20-45+ minutes, be patient)"
MEM_MB=$(awk '/MemTotal/{print int($2/1024)}' /proc/meminfo)
BUILD_JOBS=$((MEM_MB / 2000))
[[ $BUILD_JOBS -lt 1 ]] && BUILD_JOBS=1
[[ $BUILD_JOBS -gt $(nproc) ]] && BUILD_JOBS=$(nproc)
cd /opt/valhalla
$STD cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DENABLE_SINGLE_FILES_WERROR=OFF
$STD cmake --build build -- -j"$BUILD_JOBS"
$STD cmake --install build
ldconfig
echo "${RELEASE#v}" >"$HOME/.valhalla"
msg_ok "Compiled Valhalla ${RELEASE}"
msg_info "Starting Service"
systemctl start valhalla
msg_ok "Started Service"
fi
msg_ok "Updated Successfully!\n"
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}:8002/status${CL}"
echo -e "${INFO}${YW}No routing tiles are built yet. Build them for your region with:${CL}"
echo -e "${TAB}${BGN}/opt/valhalla_data/build-tiles.sh https://download.geofabrik.de/<continent>/<region>-latest.osm.pbf${CL}"

View File

@@ -58,7 +58,7 @@ PG_VERSION="17" setup_postgresql
PG_DB_NAME="authentik" PG_DB_USER="authentik" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db PG_DB_NAME="authentik" PG_DB_USER="authentik" PG_DB_GRANT_SUPERUSER="true" setup_postgresql_db
XMLSEC_VERSION="1.3.12" XMLSEC_VERSION="1.3.12"
AUTHENTIK_VERSION="version/2026.8.1" AUTHENTIK_VERSION="version/2026.8.2"
fetch_and_deploy_gh_release "xmlsec" "lsh123/xmlsec" "tarball" "${XMLSEC_VERSION}" "/opt/xmlsec" fetch_and_deploy_gh_release "xmlsec" "lsh123/xmlsec" "tarball" "${XMLSEC_VERSION}" "/opt/xmlsec"
fetch_and_deploy_gh_release "authentik" "goauthentik/authentik" "tarball" "${AUTHENTIK_VERSION}" "/opt/authentik" fetch_and_deploy_gh_release "authentik" "goauthentik/authentik" "tarball" "${AUTHENTIK_VERSION}" "/opt/authentik"
GO_VERSION="$(grep -m1 '^go ' /opt/authentik/go.mod | awk '{print $2}')" setup_go GO_VERSION="$(grep -m1 '^go ' /opt/authentik/go.mod | awk '{print $2}')" setup_go

125
install/borg-ui-install.sh Normal file
View File

@@ -0,0 +1,125 @@
#!/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/karanhudia/borg-ui
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 \
python3-dev \
pkg-config \
libffi-dev \
libssl-dev \
libacl1-dev \
liblz4-dev \
libzstd-dev \
libxxhash-dev \
libfuse3-dev \
fuse3 \
rsync \
sshfs \
openssh-client
msg_ok "Installed Dependencies"
UV_PYTHON="3.12" setup_uv
NODE_VERSION="22" setup_nodejs
fetch_and_deploy_gh_release "borg-ui" "karanhudia/borg-ui" "tarball"
# Only the three Borg pins appear in every release of this file; PYTHON_VERSION
# and RCLONE_VERSION were added upstream after v2.2.6, so both fall back.
RUNTIME_ENV="/opt/borg-ui/docker/runtime-base.env"
BORG1_VERSION=$(sed -n 's/^BORG1_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG2_VERSION=$(sed -n 's/^BORG2_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORGSTORE_VERSION=$(sed -n 's/^BORGSTORE_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
RCLONE_VERSION=$(sed -n 's/^RCLONE_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG_PYTHON=$(sed -n 's/^PYTHON_VERSION=//p' "$RUNTIME_ENV" 2>/dev/null | tr -d ' \r')
BORG_PYTHON="${BORG_PYTHON:-3.12}"
if [[ -z "$BORG1_VERSION" || -z "$BORG2_VERSION" || -z "$BORGSTORE_VERSION" ]]; then
msg_error "Could not read the pinned Borg versions from ${RUNTIME_ENV}"
exit 1
fi
msg_info "Installing Borg ${BORG1_VERSION} and Borg ${BORG2_VERSION} (Patience)"
$STD uv venv --python "$BORG_PYTHON" /opt/borg1-venv
$STD uv pip install --python /opt/borg1-venv pyfuse3 "borgbackup==${BORG1_VERSION}"
echo "$BORG1_VERSION" >/opt/borg1-venv/.pinned_version
$STD uv venv --python "$BORG_PYTHON" /opt/borg2-venv
$STD uv pip install --python /opt/borg2-venv pyfuse3 "borgbackup==${BORG2_VERSION}" "borgstore[rclone,sftp,rest,s3,blake3]==${BORGSTORE_VERSION}"
echo "${BORG2_VERSION}-${BORGSTORE_VERSION}" >/opt/borg2-venv/.pinned_version
ln -sf /opt/borg1-venv/bin/borg /usr/local/bin/borg
ln -sf /opt/borg2-venv/bin/borg /usr/local/bin/borg2
msg_ok "Installed Borg ${BORG1_VERSION} and Borg ${BORG2_VERSION}"
RCLONE_TAG="${RCLONE_VERSION:+v${RCLONE_VERSION}}"
fetch_and_deploy_gh_release "rclone" "rclone/rclone" "prebuild" "${RCLONE_TAG:-latest}" "/opt/rclone" "rclone-${RCLONE_TAG:-*}-linux-$(arch_resolve amd64 arm64).zip"
ln -sf /opt/rclone/rclone /usr/local/bin/rclone
msg_info "Building Frontend"
cd /opt/borg-ui/frontend
$STD npm ci
$STD npm run build
mkdir -p /opt/borg-ui/app/static
cp -r /opt/borg-ui/frontend/build/* /opt/borg-ui/app/static/
msg_ok "Built Frontend"
msg_info "Setting up Python Environment"
cd /opt/borg-ui
$STD uv venv --python "$BORG_PYTHON" /opt/borg-ui/.venv
$STD uv pip install --python /opt/borg-ui/.venv -r requirements.txt
msg_ok "Set up Python Environment"
msg_info "Configuring Borg-UI"
mkdir -p /opt/borg-ui_data
BORG_UI_VERSION=$(cat "$HOME/.borg-ui" 2>/dev/null)
if [[ -z "$BORG_UI_VERSION" ]]; then
msg_error "Could not determine the deployed Borg-UI version"
exit 1
fi
cat <<EOF >/opt/borg-ui/.env
APP_VERSION=${BORG_UI_VERSION}
PORT=8081
ENVIRONMENT=production
TZ=UTC
DATA_DIR=/opt/borg-ui_data
ENABLE_CRON_BACKUPS=true
ENABLE_STARTUP_LICENSE_SYNC=false
EOF
chmod 600 /opt/borg-ui/.env
msg_ok "Configured Borg-UI"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/borg-ui.service
[Unit]
Description=Borg-UI
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/borg-ui
EnvironmentFile=/opt/borg-ui/.env
ExecStart=/opt/borg-ui/.venv/bin/gunicorn app.main:app --bind 0.0.0.0:8081 --workers 2 --worker-class uvicorn.workers.UvicornWorker --timeout 300
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now borg-ui
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

View File

@@ -32,7 +32,7 @@ msg_info "Installing Calibre (for eBook conversion)"
$STD apt install -y calibre $STD apt install -y calibre
msg_ok "Installed Calibre" msg_ok "Installed Calibre"
fetch_and_deploy_gh_release "Calibre-Web" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibreweb*.tar.gz" fetch_and_deploy_gh_release "calibreweb" "janeczku/calibre-web" "prebuild" "latest" "/opt/calibre-web" "calibreweb*.tar.gz"
setup_uv setup_uv
msg_info "Installing Python Dependencies" msg_info "Installing Python Dependencies"

View File

@@ -62,6 +62,7 @@ mkdir /opt/browserless
$STD /opt/changedetection/.venv/bin/python -m pip install playwright $STD /opt/changedetection/.venv/bin/python -m pip install playwright
$STD git clone https://github.com/browserless/chrome /opt/browserless $STD git clone https://github.com/browserless/chrome /opt/browserless
$STD npm ci --include=optional --include=dev --prefix /opt/browserless $STD npm ci --include=optional --include=dev --prefix /opt/browserless
$STD npm install --save-exact playwright-core@1.62.1 --prefix /opt/browserless
$STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps &>/dev/null $STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps &>/dev/null
$STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome &>/dev/null $STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome &>/dev/null
$STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit &>/dev/null $STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit &>/dev/null

View File

@@ -25,7 +25,13 @@ $STD apt install -y \
procps \ procps \
vlc-bin \ vlc-bin \
vlc-plugin-base \ vlc-plugin-base \
streamlink streamlink \
autoconf \
libtool \
libargtable2-dev \
libavformat-dev \
libsdl2-dev \
libswscale-dev
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
setup_uv setup_uv
@@ -33,6 +39,15 @@ NODE_VERSION="24" setup_nodejs
PG_VERSION="16" setup_postgresql PG_VERSION="16" setup_postgresql
PG_DB_NAME="dispatcharr_db" PG_DB_USER="dispatcharr_usr" setup_postgresql_db PG_DB_NAME="dispatcharr_db" PG_DB_USER="dispatcharr_usr" setup_postgresql_db
fetch_and_deploy_gh_release "dispatcharr" "Dispatcharr/Dispatcharr" "tarball" fetch_and_deploy_gh_release "dispatcharr" "Dispatcharr/Dispatcharr" "tarball"
fetch_and_deploy_gh_release "Comskip" "erikkaashoek/Comskip" "tarball"
msg_info "Compiling Comskip"
cd /opt/Comskip
$STD ./autogen.sh
$STD ./configure
$STD make
$STD make install
msg_ok "Compiled and Installed Comskip"
msg_info "Installing Python Dependencies with uv" msg_info "Installing Python Dependencies with uv"
cd /opt/dispatcharr cd /opt/dispatcharr

View File

@@ -0,0 +1,70 @@
#!/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://www.elastic.co/elasticsearch
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
# vm.max_map_count is not namespaced, so a container cannot raise it - the value
# is inherited from the Proxmox host. Elasticsearch refuses to start below the
# required limit once it binds to a non-loopback address (production mode).
msg_info "Checking Kernel Limits"
if (($(sysctl -n vm.max_map_count) < 262144)); then
msg_error "vm.max_map_count is $(sysctl -n vm.max_map_count), Elasticsearch needs at least 262144"
msg_error "Set it on the PROXMOX HOST, not in this container:"
msg_error " echo 'vm.max_map_count=1048576' >/etc/sysctl.d/99-elasticsearch.conf && sysctl --system"
exit 1
fi
msg_ok "Checked Kernel Limits"
JAVA_VERSION="21" setup_java
setup_deb822_repo \
"elasticsearch" \
"https://artifacts.elastic.co/GPG-KEY-elasticsearch" \
"https://artifacts.elastic.co/packages/9.x/apt" \
"stable" \
"main"
msg_info "Installing Elasticsearch"
$STD apt install -y elasticsearch
msg_ok "Installed Elasticsearch"
msg_info "Configuring Elasticsearch"
mkdir -p /opt/elasticsearch_data
chown -R elasticsearch:elasticsearch /opt/elasticsearch_data
cat <<EOF >/etc/elasticsearch/elasticsearch.yml
cluster.name: proxmox
node.name: ${HOSTNAME}
path.data: /opt/elasticsearch_data
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
EOF
cat <<EOF >/etc/elasticsearch/jvm.options.d/heap.options
-Xms1g
-Xmx1g
EOF
systemctl enable -q --now elasticsearch
msg_ok "Configured Elasticsearch"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,96 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/gotenberg/gotenberg
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 \
chromium \
libreoffice-writer \
libreoffice-calc \
libreoffice-impress \
libreoffice-draw \
libreoffice-math \
python3-uno \
python-is-python3 \
pdftk-java \
qpdf \
libimage-exiftool-perl \
fonts-crosextra-carlito \
fonts-crosextra-caladea \
fonts-liberation \
fonts-liberation2 \
fonts-dejavu \
fonts-noto-cjk \
fonts-noto-color-emoji \
fonts-noto-core
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "pdfcpu" "pdfcpu/pdfcpu" "prebuild" "latest" "/opt/pdfcpu" "pdfcpu_*_Linux_$(arch_resolve "x86_64" "arm64").tar.xz"
ln -sf "$(find /opt/pdfcpu -type f -name pdfcpu | head -n1)" /usr/local/bin/pdfcpu
msg_info "Installing unoconverter"
UNOCONVERTER_VERSION=$(get_latest_github_release "gotenberg/unoconverter" "false")
download_file "https://raw.githubusercontent.com/gotenberg/unoconverter/${UNOCONVERTER_VERSION}/unoconv" /usr/local/bin/unoconverter
chmod +x /usr/local/bin/unoconverter
msg_ok "Installed unoconverter"
fetch_and_deploy_gh_release "gotenberg" "gotenberg/gotenberg" "tarball" "latest" "/opt/gotenberg"
GO_VERSION="$(awk '$1=="go"{print $2}' /opt/gotenberg/go.mod | cut -d. -f1,2)" setup_go
msg_info "Building Gotenberg (Patience)"
cd /opt/gotenberg
export CGO_ENABLED=0
$STD go mod download
$STD go build -o /usr/local/bin/gotenberg \
-ldflags "-s -w -X 'github.com/gotenberg/gotenberg/v8/cmd.Version=$(cat ~/.gotenberg)'" \
cmd/gotenberg/main.go
msg_ok "Built Gotenberg"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/gotenberg.service
[Unit]
Description=Gotenberg
Documentation=https://gotenberg.dev
After=network.target
[Service]
Type=simple
User=root
Environment=LANG=C.UTF-8
Environment=LC_ALL=C.UTF-8
Environment=PDFTK_BIN_PATH=/usr/bin/pdftk
Environment=QPDF_BIN_PATH=/usr/bin/qpdf
Environment=EXIFTOOL_BIN_PATH=/usr/bin/exiftool
Environment=PDFCPU_BIN_PATH=/usr/local/bin/pdfcpu
Environment=CHROMIUM_BIN_PATH=/usr/bin/chromium
Environment=CHROMIUM_HYPHEN_DATA_DIR_PATH=/opt/gotenberg/build/chromium-hyphen-data
Environment=LIBREOFFICE_BIN_PATH=/usr/lib/libreoffice/program/soffice.bin
Environment=UNOCONVERTER_BIN_PATH=/usr/local/bin/unoconverter
Environment=OTEL_TRACES_EXPORTER=none
Environment=OTEL_METRICS_EXPORTER=none
Environment=OTEL_LOGS_EXPORTER=none
ExecStart=/usr/local/bin/gotenberg --api-port=3000
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now gotenberg
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc

100
install/hammer-install.sh Normal file
View File

@@ -0,0 +1,100 @@
#!/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/Darkrock-Studios/hammer-editor
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 \
unzip \
fontconfig \
libfreetype6
msg_ok "Installed Dependencies"
JAVA_VERSION="21" setup_java
fetch_and_deploy_gh_release "hammer" "Darkrock-Studios/hammer-editor" "prebuild" "latest" "/opt/hammer" "server.zip"
msg_info "Configuring Hammer Sync Server"
chmod +x /opt/hammer/bin/server
mkdir -p /opt/hammer_data
cat <<EOF >/opt/hammer_data/config.toml
# Hammer Sync Server configuration
# Reference: https://github.com/Darkrock-Studios/hammer-editor/blob/develop/docs/HOW-TO-RUN-A-SERVER.md
# Loaded automatically from the data directory. Apply changes with:
# systemctl restart hammer
host = "${LOCAL_IP}"
port = 8080
# Hammer clients speak https only and will not connect to plain HTTP. Either put
# a TLS reverse proxy in front of this port, or let Hammer terminate TLS itself
# with a real certificate (self-signed certs are rejected by the clients).
#
# Behind a reverse proxy on this host, restrict the plain port to loopback and
# set the URL the clients actually use:
# bindHosts = ["127.0.0.1", "::1"]
# publicUrl = "https://hammer.example.com"
#
# Hammer terminating TLS itself:
# sslPort = 443
# [sslCert]
# certChainPath = "/etc/letsencrypt/live/hammer.example.com/fullchain.pem"
# privateKeyPath = "/etc/letsencrypt/live/hammer.example.com/privkey.pem"
# forceHttps = true
# Per-page social share images. fontconfig and libfreetype6 are already installed.
# richLinkPreviews = true
# communityEnabled = true
# Storage defaults to an in-process PostgreSQL under /opt/hammer_data/pgdata.
# To use an external PostgreSQL instead:
# [storage]
# type = "remote"
# [storage.remote]
# host = "db.example.com"
# port = 5432
# database = "hammer"
# user = "hammer"
# password = "change-me"
# useSsl = true
# Regenerable render/preview caches, default <data dir>/cache.
# [cache]
# directory = "/var/tmp/hammer-cache"
# maxSizeMb = 200
EOF
cat <<EOF >/etc/systemd/system/hammer.service
[Unit]
Description=Hammer Sync Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/hammer
Environment=SERVER_OPTS=-Duser.home=/opt
ExecStart=/opt/hammer/bin/server
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now hammer
msg_ok "Configured Hammer Sync Server"
motd_ssh
customize
cleanup_lxc

View File

@@ -64,7 +64,7 @@ RestartSec=1
User=root User=root
WorkingDirectory=/opt/homepage/ WorkingDirectory=/opt/homepage/
Environment=CI=true Environment=CI=true
ExecStart=pnpm start ExecStart=/opt/homepage/node_modules/.bin/next start
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -353,7 +353,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.2.0" "$SRC_DIR" fetch_and_deploy_gh_release "Immich" "immich-app/immich" "tarball" "v3.2.1" "$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

View File

@@ -28,7 +28,7 @@ if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
exit 10 exit 10
fi fi
NODE_VERSION="26" NPM_VERSION="11" setup_nodejs NODE_VERSION="24" NPM_VERSION="11" setup_nodejs
msg_info "Installing ioBroker (Patience)" msg_info "Installing ioBroker (Patience)"
$STD bash <(curl -fsSL https://iobroker.net/install.sh) $STD bash <(curl -fsSL https://iobroker.net/install.sh)

View File

@@ -13,6 +13,29 @@ setting_up_container
network_check network_check
update_os update_os
# Optional public setup. Leave the hostname empty for a LAN-only install
# (container IP, self-signed certificate) - the previous default behaviour.
if [[ -z "${var_jitsi_domain:-}" ]]; then
read -rp "${TAB3}Public hostname (FQDN, leave empty to use the container IP): " var_jitsi_domain || true
fi
var_jitsi_domain="${var_jitsi_domain:-$LOCAL_IP}"
if [[ "$var_jitsi_domain" != "$LOCAL_IP" ]]; then
if [[ -z "${var_jitsi_le_email:-}" ]]; then
read -rp "${TAB3}E-mail for Let's Encrypt (leave empty for a self-signed certificate): " var_jitsi_le_email || true
fi
if [[ -z "${var_jitsi_public_ip:-}" ]]; then
read -rp "${TAB3}Public IP behind NAT (leave empty to detect via STUN): " var_jitsi_public_ip || true
fi
if [[ -z "${var_jitsi_admin_user:-}" ]]; then
read -rp "${TAB3}Admin user for secure domain (leave empty to let anyone create rooms): " var_jitsi_admin_user || true
fi
if [[ -n "${var_jitsi_admin_user:-}" && -z "${var_jitsi_admin_pass:-}" ]]; then
read -rsp "${TAB3}Admin password (leave empty to generate): " var_jitsi_admin_pass || true
echo
fi
fi
msg_info "Installing Dependencies" msg_info "Installing Dependencies"
$STD apt install -y nginx $STD apt install -y nginx
msg_ok "Installed Dependencies" msg_ok "Installed Dependencies"
@@ -25,11 +48,72 @@ setup_deb822_repo "jitsi" \
"" ""
msg_info "Installing Jitsi Meet" msg_info "Installing Jitsi Meet"
echo "jitsi-videobridge2 jitsi-videobridge/jvb-hostname string ${LOCAL_IP}" | debconf-set-selections echo "jitsi-videobridge2 jitsi-videobridge/jvb-hostname string ${var_jitsi_domain}" | debconf-set-selections
echo "jitsi-meet-web-config jitsi-meet/cert-choice select Generate a new self-signed certificate" | debconf-set-selections if [[ -n "${var_jitsi_le_email:-}" ]]; then
# acme.sh (used by the packaged Let's Encrypt helper) refuses to install without cron
$STD apt install -y cron
echo "jitsi-meet-web-config jitsi-meet/cert-choice select Let's Encrypt certificates" | debconf-set-selections
echo "jitsi-meet-web-config jitsi-meet/email string ${var_jitsi_le_email}" | debconf-set-selections
else
echo "jitsi-meet-web-config jitsi-meet/cert-choice select Generate a new self-signed certificate" | debconf-set-selections
fi
echo "jitsi-meet-web-config jitsi-meet/jaas-choice boolean false" | debconf-set-selections
DEBIAN_FRONTEND=noninteractive $STD apt install -y jitsi-meet DEBIAN_FRONTEND=noninteractive $STD apt install -y jitsi-meet
msg_ok "Installed Jitsi Meet" msg_ok "Installed Jitsi Meet"
if [[ -n "${var_jitsi_public_ip:-}" ]]; then
msg_info "Configuring NAT mapping"
# JVB 2.3+ reads this from jvb.conf; sip-communicator.properties is no longer used
cat <<EOF >>/etc/jitsi/videobridge/jvb.conf
ice4j {
harvest {
mapping {
static-mappings = [
{ local-address = "${LOCAL_IP}", public-address = "${var_jitsi_public_ip}" }
]
}
}
}
EOF
systemctl restart jitsi-videobridge2
msg_ok "Configured NAT mapping"
fi
if [[ -n "${var_jitsi_admin_user:-}" ]]; then
msg_info "Configuring Secure Domain"
# Only authenticated users may create rooms; guests join via the anonymous domain.
# https://jitsi.github.io/handbook/docs/devops-guide/secure-domain/
var_jitsi_admin_pass="${var_jitsi_admin_pass:-$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-16)}"
sed -i "0,/authentication = \"jitsi-anonymous\"/s//authentication = \"internal_hashed\"/" \
"/etc/prosody/conf.avail/${var_jitsi_domain}.cfg.lua"
cat <<EOF >>"/etc/prosody/conf.avail/${var_jitsi_domain}.cfg.lua"
VirtualHost "guest.${var_jitsi_domain}"
authentication = "anonymous"
c2s_require_encryption = false
EOF
cat <<EOF >>/etc/jitsi/jicofo/jicofo.conf
jicofo {
authentication {
enabled = true
type = XMPP
login-url = "${var_jitsi_domain}"
}
}
EOF
sed -i "s|^\s*// anonymousdomain: 'guest.example.com',| anonymousdomain: 'guest.${var_jitsi_domain}',|" \
"/etc/jitsi/meet/${var_jitsi_domain}-config.js"
$STD prosodyctl register "${var_jitsi_admin_user}" "${var_jitsi_domain}" "${var_jitsi_admin_pass}"
cat <<EOF >~/jitsi-meet.creds
Jitsi Meet Secure Domain
Admin User: ${var_jitsi_admin_user}
Admin Password: ${var_jitsi_admin_pass}
Add more users: prosodyctl register <name> ${var_jitsi_domain} <password>
EOF
systemctl restart prosody jicofo jitsi-videobridge2
msg_ok "Configured Secure Domain"
fi
motd_ssh motd_ssh
customize customize
cleanup_lxc cleanup_lxc

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Jamie (jamiej)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/lemonade-sdk/lemonade
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
setup_deb822_repo \
"backports" \
"https://ftp-master.debian.org/keys/archive-key-13.asc" \
"http://deb.debian.org/debian" \
"trixie-backports" \
"main"
msg_info "Installing Lemonade Server dependencies"
$STD apt install -y \
fonts-katex \
libcpp-httplib0.41 \
libmbedcrypto16 \
libwebsockets19t64
msg_ok "Installed Lemonade Server dependencies"
setup_hwaccel
fetch_and_deploy_gh_release "lemonade-server" "lemonade-sdk/lemonade" "binary" "latest" "/tmp" "lemonade-server_*-debian13_$(arch_resolve).deb"
msg_info "Configuring Remote Access"
systemctl enable -q --now lemond
for _ in $(seq 1 60); do
lemonade status >/dev/null 2>&1 && break
sleep 2
done
$STD lemonade config set host=0.0.0.0
systemctl restart lemond
msg_ok "Configured Remote Access"
motd_ssh
customize
cleanup_lxc

View File

@@ -0,0 +1,138 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: Hai Tran (epiHATR)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://onetimesecret.com/ | Github: https://github.com/onetimesecret/onetimesecret
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 \
git \
libffi-dev \
libgmp-dev \
libpq-dev \
libreadline-dev \
libsodium23 \
libsqlite3-dev \
libssl-dev \
libxml2-dev \
libxslt1-dev \
libyaml-dev \
nginx \
pkg-config \
python3 \
redis-server \
zlib1g-dev
msg_ok "Installed Dependencies"
fetch_and_deploy_gh_release "onetimesecret" "onetimesecret/onetimesecret" "tarball"
RUBY_VERSION=$(tr -d ' \n' </opt/onetimesecret/.ruby-version 2>/dev/null)
RUBY_VERSION="${RUBY_VERSION:-3.4.10}" setup_ruby
PNPM_VERSION=$(sed -n 's/.*"packageManager": "pnpm@\([^"]*\)".*/\1/p' /opt/onetimesecret/package.json)
NODE_VERSION=$(tr -d ' \n' </opt/onetimesecret/.nvmrc 2>/dev/null)
NODE_VERSION="${NODE_VERSION:-25}" NODE_MODULE="pnpm@${PNPM_VERSION:-11.1.2}" setup_nodejs
HOST_VALUE="${OTS_HOST:-$LOCAL_IP}"
SSL_VALUE="${OTS_SSL:-false}"
case "${SSL_VALUE,,}" in
1 | true | yes | on) SSL_VALUE="true" ;;
0 | false | no | off | "") SSL_VALUE="false" ;;
*)
msg_error "Invalid OTS_SSL value '${OTS_SSL}' (use true/false)"
exit 1
;;
esac
msg_info "Configuring Application"
systemctl enable -q --now redis-server
cd /opt/onetimesecret
$STD bash bin/setup init
sed -i \
-e "s|^REDIS_URL=.*|REDIS_URL=redis://127.0.0.1:6379/0|" \
-e "s|^HOST=.*|HOST=${HOST_VALUE//&/\\&}|" \
-e "s|^SSL=.*|SSL=${SSL_VALUE}|" \
/opt/onetimesecret/.env
if grep -q '^RACK_ENV=' /opt/onetimesecret/.env; then
sed -i 's|^RACK_ENV=.*|RACK_ENV=production|' /opt/onetimesecret/.env
else
echo "RACK_ENV=production" >>/opt/onetimesecret/.env
fi
if grep -q '^AUTHENTICATION_MODE=' /opt/onetimesecret/.env; then
sed -i 's|^AUTHENTICATION_MODE=.*|AUTHENTICATION_MODE=simple|' /opt/onetimesecret/.env
else
echo "AUTHENTICATION_MODE=simple" >>/opt/onetimesecret/.env
fi
if ! grep -q '^PORT=' /opt/onetimesecret/.env; then
echo "PORT=3000" >>/opt/onetimesecret/.env
fi
chmod 600 /opt/onetimesecret/.env
mkdir -p /opt/onetimesecret/tmp/pids /opt/onetimesecret/log
msg_ok "Configured Application"
msg_info "Reconciling Application"
cd /opt/onetimesecret
$STD bash bin/setup reconcile
msg_ok "Reconciled Application"
msg_info "Building Frontend"
cd /opt/onetimesecret
$STD pnpm run build
msg_ok "Built Frontend"
msg_info "Creating Service"
cat <<'EOF' >/etc/systemd/system/onetimesecret.service
[Unit]
Description=Onetime Secret Service
After=network.target redis-server.service
Requires=redis-server.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/onetimesecret
Environment=HOME=/root
Environment=PATH=/root/.rbenv/shims:/root/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
EnvironmentFile=/opt/onetimesecret/.env
ExecStart=/root/.rbenv/shims/bundle exec puma -C etc/puma.rb
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now onetimesecret
msg_ok "Created Service"
msg_info "Configuring Nginx"
cat <<'EOF' >/etc/nginx/sites-available/onetimesecret
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
nginx_enable_site onetimesecret
msg_ok "Configured Nginx"
motd_ssh
customize
cleanup_lxc

View File

@@ -23,6 +23,7 @@ msg_ok "Installed Dependencies"
NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs NODE_VERSION="24" NODE_MODULE="pnpm" setup_nodejs
PG_VERSION="17" setup_postgresql PG_VERSION="17" setup_postgresql
PG_DB_NAME="paperclip" PG_DB_USER="paperclip" setup_postgresql_db PG_DB_NAME="paperclip" PG_DB_USER="paperclip" setup_postgresql_db
setup_rust
fetch_and_deploy_gh_release "paperclip-ai" "paperclipai/paperclip" "tarball" fetch_and_deploy_gh_release "paperclip-ai" "paperclipai/paperclip" "tarball"

View File

@@ -151,7 +151,7 @@ Requires=redis.service
[Service] [Service]
WorkingDirectory=/opt/paperless/src WorkingDirectory=/opt/paperless/src
#ExecStartPre=uv run -- python manage.py document_index reindex --if-needed --no-progress-bar #ExecStartPre=uv run --no-sync -- python manage.py document_index reindex --if-needed --no-progress-bar
ExecStart=uv run --no-sync -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application" ExecStart=uv run --no-sync -- granian --interface asginl --ws --loop uvloop "paperless.asgi:application"
Environment=GRANIAN_HOST=:: Environment=GRANIAN_HOST=::
Environment=GRANIAN_PORT=8000 Environment=GRANIAN_PORT=8000

View File

@@ -46,7 +46,7 @@ map \$uri \$poznote_coop {
server { server {
listen 8040; listen 8040;
root /var/www/html; root /var/www/html/public;
index index.php index.html; index index.php index.html;
gzip on; gzip on;
@@ -122,10 +122,12 @@ server {
} }
location ~ ^/data/users/[0-9]+/backgrounds/ { location ~ ^/data/users/[0-9]+/backgrounds/ {
root /var/www/html;
try_files \$uri =404; try_files \$uri =404;
} }
location ~ ^/data/css/[A-Za-z0-9._-]+\.css$ { location ~ ^/data/css/[A-Za-z0-9._-]+\.css$ {
root /var/www/html;
try_files \$uri =404; try_files \$uri =404;
} }

View File

@@ -86,6 +86,7 @@ sed \
-e 's|${SPARKY_FITNESS_SERVER_PORT}|3010|g' \ -e 's|${SPARKY_FITNESS_SERVER_PORT}|3010|g' \
-e "s|\${SPARKY_FITNESS_FRONTEND_URL}|http://${LOCAL_IP}:80|g" \ -e "s|\${SPARKY_FITNESS_FRONTEND_URL}|http://${LOCAL_IP}:80|g" \
-e 's|${NGINX_LISTEN_PORT}|80|g' \ -e 's|${NGINX_LISTEN_PORT}|80|g' \
-e 's|${NGINX_RATE_LIMIT}|5r/s|g' \
-e 's|${NGINX_ACCESS_LOG}|/var/log/nginx/sparkyfitness.access.log|g' \ -e 's|${NGINX_ACCESS_LOG}|/var/log/nginx/sparkyfitness.access.log|g' \
-e 's|${NGINX_ERROR_LOG}|/var/log/nginx/sparkyfitness.error.log|g' \ -e 's|${NGINX_ERROR_LOG}|/var/log/nginx/sparkyfitness.error.log|g' \
-e 's|root /usr/share/nginx/html;|root /var/www/sparkyfitness;|g' \ -e 's|root /usr/share/nginx/html;|root /var/www/sparkyfitness;|g' \

View File

@@ -15,7 +15,7 @@ update_os
PG_VERSION="16" setup_postgresql PG_VERSION="16" setup_postgresql
PG_DB_NAME="spliit" PG_DB_USER="spliit" setup_postgresql_db PG_DB_NAME="spliit" PG_DB_USER="spliit" setup_postgresql_db
NODE_VERSION="24" setup_nodejs NODE_VERSION="26" setup_nodejs
fetch_and_deploy_gh_release "spliit" "spliit-app/spliit" "tarball" fetch_and_deploy_gh_release "spliit" "spliit-app/spliit" "tarball"
msg_info "Configuring Application" msg_info "Configuring Application"

View File

@@ -67,7 +67,7 @@ cd /opt/tracearr.build
$STD pnpm install --frozen-lockfile --force $STD pnpm install --frozen-lockfile --force
$STD pnpm turbo telemetry disable $STD pnpm turbo telemetry disable
$STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web $STD pnpm turbo run build --no-daemon --filter=@tracearr/shared --filter=@tracearr/server --filter=@tracearr/web
mkdir -p /opt/tracearr/{packages/shared,apps/server,apps/web,apps/server/src/db} mkdir -p /opt/tracearr/{packages/shared,packages/emails,apps/server,apps/web,apps/server/src/db}
cp -rf package.json /opt/tracearr/ cp -rf package.json /opt/tracearr/
cp -rf pnpm-workspace.yaml /opt/tracearr/ cp -rf pnpm-workspace.yaml /opt/tracearr/
cp -rf pnpm-lock.yaml /opt/tracearr/ cp -rf pnpm-lock.yaml /opt/tracearr/
@@ -77,6 +77,8 @@ cp -rf apps/server/scripts /opt/tracearr/apps/server/scripts
cp -rf apps/web/dist /opt/tracearr/apps/web/dist cp -rf apps/web/dist /opt/tracearr/apps/web/dist
cp -rf packages/shared/package.json /opt/tracearr/packages/shared/ cp -rf packages/shared/package.json /opt/tracearr/packages/shared/
cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist cp -rf packages/shared/dist /opt/tracearr/packages/shared/dist
cp -rf packages/emails/package.json /opt/tracearr/packages/emails/
cp -rf packages/emails/dist /opt/tracearr/packages/emails/dist
cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations cp -rf apps/server/src/db/migrations /opt/tracearr/apps/server/src/db/migrations
cp -rf data /opt/tracearr/data cp -rf data /opt/tracearr/data
mkdir -p /opt/tracearr/data/image-cache mkdir -p /opt/tracearr/data/image-cache

187
install/valhalla-install.sh Normal file
View File

@@ -0,0 +1,187 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: CrazyWolf13
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/valhalla/valhalla
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 \
autoconf \
automake \
ccache \
clang \
clang-tidy \
coreutils \
cmake \
g++ \
gcc \
git \
jq \
lcov \
libboost-all-dev \
libcurl4-openssl-dev \
libczmq-dev \
libgdal-dev \
libgeos++-dev \
libgeos-dev \
libluajit-5.1-dev \
liblz4-dev \
libprotobuf-dev \
libspatialite-dev \
libsqlite3-dev \
libsqlite3-mod-spatialite \
libtool \
libzmq3-dev \
lld \
locales \
luajit \
make \
osmium-tool \
parallel \
pkgconf \
protobuf-compiler \
python3-all-dev \
python3-shapely \
python3-requests \
python3-pip \
spatialite-bin \
unzip \
zlib1g-dev
msg_ok "Installed Dependencies"
PRIME_SERVER_RELEASE=$(get_latest_github_release "kevinkreiser/prime_server" "false")
msg_info "Building prime_server ${PRIME_SERVER_RELEASE} (Patience)"
$STD git clone --recurse-submodules --depth 1 --branch "$PRIME_SERVER_RELEASE" https://github.com/kevinkreiser/prime_server /tmp/prime_server
cd /tmp/prime_server
$STD ./autogen.sh
$STD ./configure
$STD make -j"$(nproc)"
$STD make install
cd /
rm -rf /tmp/prime_server
echo "${PRIME_SERVER_RELEASE#v}" >"$HOME/.prime_server"
msg_ok "Built prime_server"
RELEASE=$(get_latest_github_release "valhalla/valhalla" "false")
msg_info "Cloning Valhalla ${RELEASE} (Patience)"
mkdir -p /opt/valhalla
$STD git clone --recurse-submodules --depth 1 --branch "$RELEASE" https://github.com/valhalla/valhalla.git /opt/valhalla
msg_ok "Cloned Valhalla ${RELEASE}"
msg_info "Compiling Valhalla ${RELEASE} (this takes 20-45+ minutes, be patient)"
MEM_MB=$(awk '/MemTotal/{print int($2/1024)}' /proc/meminfo)
BUILD_JOBS=$((MEM_MB / 2000))
[[ $BUILD_JOBS -lt 1 ]] && BUILD_JOBS=1
[[ $BUILD_JOBS -gt $(nproc) ]] && BUILD_JOBS=$(nproc)
cd /opt/valhalla
$STD cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_PYTHON_BINDINGS=OFF -DENABLE_TESTS=OFF -DENABLE_SINGLE_FILES_WERROR=OFF
$STD cmake --build build -- -j"$BUILD_JOBS"
$STD cmake --install build
ldconfig
echo "${RELEASE#v}" >"$HOME/.valhalla"
msg_ok "Compiled Valhalla ${RELEASE}"
msg_info "Configuring Valhalla"
useradd --system --no-create-home --shell /usr/sbin/nologin valhalla 2>/dev/null || true
mkdir -p /opt/valhalla_data/{valhalla_tiles,pbf}
THREADS=$(nproc)
valhalla_build_config \
--mjolnir-tile-dir /opt/valhalla_data/valhalla_tiles \
--mjolnir-tile-extract /opt/valhalla_data/valhalla_tiles.tar \
--mjolnir-admin /opt/valhalla_data/admins.sqlite \
--mjolnir-timezone /opt/valhalla_data/timezones.sqlite \
--mjolnir-concurrency "$THREADS" \
>/opt/valhalla_data/valhalla.json
cat <<'EOF' >/opt/valhalla_data/build-tiles.sh
#!/usr/bin/env bash
# (Re)builds Valhalla routing tiles from one or more OSM extracts.
# Usage: build-tiles.sh <pbf-url-or-path> [<pbf-url-or-path> ...]
# Example: build-tiles.sh https://download.geofabrik.de/europe/germany-latest.osm.pbf
set -euo pipefail
export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
if [[ $# -eq 0 ]]; then
echo "Usage: $0 <pbf-url-or-path> [<pbf-url-or-path> ...]" >&2
exit 1
fi
DATA_DIR=/opt/valhalla_data
CONFIG="$DATA_DIR/valhalla.json"
mkdir -p "$DATA_DIR/pbf"
FILES=()
for src in "$@"; do
if [[ "$src" == http://* || "$src" == https://* ]]; then
fname="$DATA_DIR/pbf/$(basename "$src")"
echo "Downloading $src"
curl -fL --progress-bar -o "$fname" "$src"
else
fname="$src"
fi
FILES+=("$fname")
done
systemctl stop valhalla
echo "Building admin database"
valhalla_build_admins --config "$CONFIG" "${FILES[@]}"
echo "Building timezone database"
valhalla_build_timezones >"$DATA_DIR/timezones.sqlite"
echo "Building initial tile graph"
valhalla_build_tiles -c "$CONFIG" -e build "${FILES[@]}"
echo "Enhancing tile graph"
valhalla_build_tiles -c "$CONFIG" -s enhance "${FILES[@]}"
echo "Packing tiles into a single extract"
valhalla_build_extract -c "$CONFIG" -v
chown -R valhalla:valhalla "$DATA_DIR"
systemctl start valhalla
echo "Done. Tiles are in $DATA_DIR/valhalla_tiles (and packed at $DATA_DIR/valhalla_tiles.tar)."
EOF
chmod +x /opt/valhalla_data/build-tiles.sh
chown -R valhalla:valhalla /opt/valhalla_data
msg_ok "Configured Valhalla"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/valhalla.service
[Unit]
Description=Valhalla Routing Engine
After=network.target
[Service]
Type=simple
User=valhalla
Group=valhalla
WorkingDirectory=/opt/valhalla_data
ExecStart=/usr/local/bin/valhalla_service /opt/valhalla_data/valhalla.json ${THREADS}
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now valhalla
msg_ok "Created Service"
if [[ -n "${VALHALLA_PBF_URLS:-}" ]]; then
msg_info "Building Initial Tiles from VALHALLA_PBF_URLS (this can take a long time)"
$STD /opt/valhalla_data/build-tiles.sh $VALHALLA_PBF_URLS
msg_ok "Built Initial Tiles"
fi
motd_ssh
customize
cleanup_lxc

View File

@@ -15,6 +15,11 @@
[[ -n "${_CORE_FUNC_LOADED:-}" ]] && return [[ -n "${_CORE_FUNC_LOADED:-}" ]] && return
_CORE_FUNC_LOADED=1 _CORE_FUNC_LOADED=1
if [[ -z "${HOME:-}" ]]; then
HOME="$(getent passwd "$(id -u)" 2>/dev/null | cut -d: -f6)"
export HOME="${HOME:-/root}"
fi
# ============================================================================== # ==============================================================================
# SECTION 1: INITIALIZATION & SETUP # SECTION 1: INITIALIZATION & SETUP
# ============================================================================== # ==============================================================================

111
tools/addon/dockhand.sh Normal file
View File

@@ -0,0 +1,111 @@
#!/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/Finsys/dockhand
if command -v curl >/dev/null 2>&1; then
source <(curl -fsSL ${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/core.func)
load_functions
elif command -v wget >/dev/null 2>&1; then
source <(wget -qO- ${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/core.func)
load_functions
fi
source <(curl -fsSL ${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/lib/tools.func)
color
catch_errors
APP="Dockhand"
APP_TYPE="addon"
INSTALL_PATH="/opt/dockhand"
COMPOSE_FILE="${INSTALL_PATH}/docker-compose.yaml"
DEFAULT_PORT=3000
header_info "$APP"
IP=$(_get_current_ip)
function check_docker() {
if ! command -v docker >/dev/null 2>&1; then
msg_error "Docker is not installed. This addon requires an existing Docker host/LXC. Exiting."
exit 1
fi
if ! docker compose version >/dev/null 2>&1; then
msg_error "Docker Compose plugin is not available. Install it before running this addon. Exiting."
exit 1
fi
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
}
function install_dockhand() {
local port="${1:-$DEFAULT_PORT}"
check_docker
msg_info "Creating Compose Project"
mkdir -p "$INSTALL_PATH"
cat <<EOF >"$COMPOSE_FILE"
services:
dockhand:
image: fnsys/dockhand:latest
container_name: dockhand
restart: unless-stopped
ports:
- ${port}:3000
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- dockhand_data:/app/data
volumes:
dockhand_data:
EOF
msg_ok "Created Compose Project"
msg_info "Starting ${APP}"
cd "$INSTALL_PATH"
$STD docker compose up -d
msg_ok "Started ${APP}"
msg_ok "${APP} is reachable at http://${IP}:${port}"
echo -e "${TAB}Open the URL and complete the first-run setup wizard to create the admin account."
}
function update_dockhand() {
msg_info "Pulling latest ${APP} image"
cd "$INSTALL_PATH"
$STD docker compose pull
msg_ok "Pulled latest image"
msg_info "Restarting ${APP}"
$STD docker compose up -d --remove-orphans
msg_ok "Restarted ${APP}"
msg_ok "${APP} updated successfully"
}
function uninstall_dockhand() {
msg_info "Removing ${APP}"
cd "$INSTALL_PATH"
$STD docker compose down --remove-orphans
cd /
rm -rf "$INSTALL_PATH"
msg_ok "${APP} uninstalled (the dockhand_data volume was kept; remove it with: docker volume rm dockhand_data)"
}
if [[ -f "$COMPOSE_FILE" ]]; then
read -r -p "Update (1), Uninstall (2), Cancel (3)? [1/2/3]: " action
action="${action//[[:space:]]/}"
case "$action" in
1) update_dockhand ;;
2) uninstall_dockhand ;;
3) msg_info "Cancelled" ;;
*) msg_error "Invalid input" ;;
esac
else
read -r -p "Enter port number (default: ${DEFAULT_PORT}): " PORT_INPUT
PORT="${PORT_INPUT:-$DEFAULT_PORT}"
read -r -p "Install ${APP}? (y/n): " answer
answer="${answer//[[:space:]]/}"
[[ "${answer,,}" =~ ^(y|yes)$ ]] && install_dockhand "$PORT" || msg_info "Installation skipped"
fi

6
tools/headers/dockhand Normal file
View File

@@ -0,0 +1,6 @@
____ __ __ __
/ __ \____ _____/ /__/ /_ ____ _____ ____/ /
/ / / / __ \/ ___/ //_/ __ \/ __ `/ __ \/ __ /
/ /_/ / /_/ / /__/ ,< / / / / /_/ / / / / /_/ /
/_____/\____/\___/_/|_/_/ /_/\__,_/_/ /_/\__,_/

View File

@@ -40,7 +40,7 @@ CM="${TAB}✔️${TAB}${CL}"
# Telemetry # 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 "lxc-delete" "pve" declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "guest-delete" "pve"
GUEST_LOG=$(mktemp) GUEST_LOG=$(mktemp)
trap 'rm -f "$GUEST_LOG"' EXIT trap 'rm -f "$GUEST_LOG"' EXIT

View File

@@ -45,6 +45,8 @@ add() {
excluded_instances=("$@") excluded_instances=("$@")
echo "Excluded instances: ${excluded_instances[@]}" echo "Excluded instances: ${excluded_instances[@]}"
value_of() { sed -n "s/^$1:[[:space:]]*//p" <<<"$config" | head -n1; }
while true; do while true; do
for instance in $(pct list | awk 'NR>1 {print $1}'; qm list | awk 'NR>1 {print $1}'); do for instance in $(pct list | awk 'NR>1 {print $1}'; qm list | awk 'NR>1 {print $1}'); do
@@ -59,21 +61,21 @@ while true; do
if [ -r "/etc/pve/lxc/$instance.conf" ]; then if [ -r "/etc/pve/lxc/$instance.conf" ]; then
type="ct" type="ct"
config_file="/etc/pve/lxc/$instance.conf" config_file="/etc/pve/lxc/$instance.conf"
else elif [ -r "/etc/pve/qemu-server/$instance.conf" ]; then
type="vm" type="vm"
config_file="/etc/pve/qemu-server/$instance.conf" config_file="/etc/pve/qemu-server/$instance.conf"
else
echo "Skipping $instance because its config is no longer readable"
continue
fi fi
config=$(sed '/^\[/,$d' "$config_file") config=$(sed '/^\[/,$d' "$config_file")
# Skip templates and onboot-disabled # Both are booleans that Proxmox also writes as 0, so the value decides and
if grep -q "onboot: 0" <<<"$config" || ! grep -q "onboot" <<<"$config"; then # not the presence of the key.
onboot="true" [ "$(value_of onboot)" = "1" ] && onboot="true" || onboot="false"
else [ "$(value_of template)" = "1" ] && template="true" || template="false"
onboot="false"
fi
template=$(grep -q "^template:" <<<"$config" && echo "true" || echo "false")
if [ "$onboot" == "true" ]; then if [ "$onboot" != "true" ]; then
echo "Skipping $instance because it is set not to boot" echo "Skipping $instance because it is set not to boot"
continue continue
elif [ "$template" == "true" ]; then elif [ "$template" == "true" ]; then
@@ -81,34 +83,40 @@ while true; do
continue continue
fi fi
# Check for mon-restart tag # Tags are semicolon separated, so match a whole entry instead of a
has_tag=$(grep -q "tags:.*mon-restart" <<<"$config" && echo "true" || echo "false") # substring of a longer tag such as mon-restart-disabled.
if [ "$has_tag" != "true" ]; then tags=";$(value_of tags | tr -d '[:space:]');"
if [[ "$tags" != *";mon-restart;"* ]]; then
echo "Skipping $instance because it does not have 'mon-restart' tag" echo "Skipping $instance because it does not have 'mon-restart' tag"
continue continue
fi fi
# Responsiveness check and restart if needed # Responsiveness check and restart if needed
if [ "$type" == "vm" ]; then if [ "$type" == "vm" ]; then
# Check if guest agent responds if ! qm status "$instance" 2>/dev/null | grep -q "status: running"; then
if qm guest cmd $instance ping >/dev/null 2>&1; then echo "$(date): VM $instance is not running, starting..."
qm start "$instance" >/dev/null 2>&1
elif qm guest cmd "$instance" ping >/dev/null 2>&1; then
echo "VM $instance is responsive via guest agent" echo "VM $instance is responsive via guest agent"
else else
echo "$(date): VM $instance is not responding to agent ping, restarting..." echo "$(date): VM $instance is not responding to agent ping, restarting..."
if qm status $instance | grep -q "status: running"; then qm stop "$instance" >/dev/null 2>&1
qm stop $instance >/dev/null 2>&1 sleep 5
sleep 5 qm start "$instance" >/dev/null 2>&1
fi
qm start $instance >/dev/null 2>&1
fi fi
else else
# Container: get IP and ping if ! pct status "$instance" 2>/dev/null | grep -q "status: running"; then
IP=$(pct exec $instance ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1) echo "$(date): CT $instance is not running, starting..."
if ! ping -c 1 $IP >/dev/null 2>&1; then pct start "$instance" >/dev/null 2>&1
continue
fi
# Not every container names its interface eth0.
IP=$(pct exec "$instance" -- ip -4 -o addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -n1)
if [ -z "$IP" ] || ! ping -c 1 -W 2 "$IP" >/dev/null 2>&1; then
echo "$(date): CT $instance is not responding, restarting..." echo "$(date): CT $instance is not responding, restarting..."
pct stop $instance >/dev/null 2>&1 pct stop "$instance" >/dev/null 2>&1
sleep 5 sleep 5
pct start $instance >/dev/null 2>&1 pct start "$instance" >/dev/null 2>&1
else else
echo "CT $instance is responsive" echo "CT $instance is responsive"
fi fi
@@ -124,23 +132,18 @@ EOF
touch /var/log/ping-instances.log touch /var/log/ping-instances.log
chmod +x /usr/local/bin/ping-instances.sh chmod +x /usr/local/bin/ping-instances.sh
cat <<EOF >/etc/systemd/system/ping-instances.timer # The service loops with its own five minute sleep, so the timer that earlier
[Unit] # versions installed could only ever start a unit that was already running.
Description=Delay ping-instances.service by 5 minutes if [[ -f /etc/systemd/system/ping-instances.timer ]]; then
systemctl disable -q --now ping-instances.timer 2>/dev/null || true
[Timer] rm -f /etc/systemd/system/ping-instances.timer
OnBootSec=300 fi
OnUnitActiveSec=300
[Install]
WantedBy=timers.target
EOF
cat <<EOF >/etc/systemd/system/ping-instances.service cat <<EOF >/etc/systemd/system/ping-instances.service
[Unit] [Unit]
Description=Ping instances every 5 minutes and restart if necessary Description=Ping instances every 5 minutes and restart if necessary
After=ping-instances.timer After=pve-cluster.service
Requires=ping-instances.timer Wants=pve-cluster.service
[Service] [Service]
Type=simple Type=simple
@@ -158,7 +161,6 @@ WantedBy=multi-user.target
EOF EOF
systemctl daemon-reload systemctl daemon-reload
systemctl enable -q --now ping-instances.timer
systemctl enable -q --now ping-instances.service systemctl enable -q --now ping-instances.service
clear clear
echo -e "\n Monitor All installed." echo -e "\n Monitor All installed."
@@ -167,7 +169,7 @@ EOF
} }
remove() { remove() {
systemctl disable -q --now ping-instances.timer systemctl disable -q --now ping-instances.timer 2>/dev/null || true
systemctl disable -q --now ping-instances.service systemctl disable -q --now ping-instances.service
rm -f /etc/systemd/system/ping-instances.service rm -f /etc/systemd/system/ping-instances.service
rm -f /etc/systemd/system/ping-instances.timer rm -f /etc/systemd/system/ping-instances.timer

View File

@@ -178,6 +178,24 @@ function resolve_service_script() {
return 1 return 1
} }
# The retired Gitea mirror. The old entrypoint pulls ct/<app>.sh straight from
# it and never reaches the update helper that would repair itself, so rewrite it
# here. Only host and /raw/<kind>/ change; owner, repo and ref are kept.
function repair_update_url() {
local container="$1"
pct exec "$container" -- sh -c '
[ -f /usr/bin/update ] || exit 1
grep -q git.community-scripts.org /usr/bin/update || exit 1
sed -i \
-e "s|https://git[.]community-scripts[.]org/|https://raw.githubusercontent.com/|g" \
-e "s|/raw/branch/|/|g" -e "s|/raw/tag/|/|g" -e "s|/raw/commit/|/|g" \
/usr/bin/update
' >/dev/null 2>&1 || return 1
echo -e "${BL}[INFO]${CL} Repaired update URL (Gitea -> GitHub) in container $container"
log_write "Container $container: rewrote the retired Gitea base in /usr/bin/update"
}
function detect_service() { function detect_service() {
local container="$1" local container="$1"
local tmpdir update_file local tmpdir update_file
@@ -489,6 +507,9 @@ for container in $CHOICE; do
sleep 5 sleep 5
fi fi
#0.5) Rewrite a retired Gitea base before anything reads it.
repair_update_url "$container"
#1) Detect service using the service name in the update command #1) Detect service using the service name in the update command
detect_service $container detect_service $container

View File

@@ -2,15 +2,15 @@
# Copyright (c) 2021-2026 community-scripts ORG # Copyright (c) 2021-2026 community-scripts ORG
# Author: thost96 (thost96) | michelroegl-brunner | MickLesk # Author: thost96 (thost96) | michelroegl-brunner | MickLesk
# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# ============================================================================== # ==============================================================================
# Docker VM - Creates a Docker-ready Virtual Machine # Docker VM - Creates a Docker-ready Virtual Machine
# ============================================================================== # ==============================================================================
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main}"
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/vm-core.func) source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/pve/vm-core.func")
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/cloud-init.func) || true load_functions
# ============================================================================== # ==============================================================================
# SCRIPT VARIABLES # SCRIPT VARIABLES
@@ -32,8 +32,6 @@ OS_VERSION=""
THIN="discard=on,ssd=1," THIN="discard=on,ssd=1,"
var_arm64="yes" var_arm64="yes"
load_functions
# ============================================================================== # ==============================================================================
# ERROR HANDLING & CLEANUP # ERROR HANDLING & CLEANUP
# ============================================================================== # ==============================================================================
@@ -44,73 +42,70 @@ trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"
local command="$2"
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
post_update_to_api "failed" "${exit_code}"
echo -e "\n$error_message\n"
cleanup_vmid
}
# ============================================================================== # ==============================================================================
# OS SELECTION FUNCTIONS # OS SELECTION FUNCTIONS
# ============================================================================== # ==============================================================================
function select_os() { function select_os() {
if OS_CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT OS" --radiolist \ if [[ "${VM_UNATTENDED:-0}" == "1" ]]; then
"Choose Operating System for Docker VM" 14 68 4 \ OS_CHOICE="${VM_OS_VERSION:-debian13}"
elif ! OS_CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SELECT OS" --radiolist \
"Choose Operating System for Docker VM" 15 68 5 \
"debian13" "Debian 13 (Trixie) - Latest" ON \ "debian13" "Debian 13 (Trixie) - Latest" ON \
"debian12" "Debian 12 (Bookworm) - Stable" OFF \ "debian12" "Debian 12 (Bookworm) - Stable" OFF \
"ubuntu2604" "Ubuntu 26.04 LTS (Resolute)" OFF \
"ubuntu2404" "Ubuntu 24.04 LTS (Noble)" OFF \ "ubuntu2404" "Ubuntu 24.04 LTS (Noble)" OFF \
"ubuntu2204" "Ubuntu 22.04 LTS (Jammy)" OFF \ "ubuntu2204" "Ubuntu 22.04 LTS (Jammy)" OFF \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
case $OS_CHOICE in
debian13)
OS_TYPE="debian"
OS_VERSION="13"
OS_CODENAME="trixie"
OS_DISPLAY="Debian 13 (Trixie)"
;;
debian12)
OS_TYPE="debian"
OS_VERSION="12"
OS_CODENAME="bookworm"
OS_DISPLAY="Debian 12 (Bookworm)"
;;
ubuntu2404)
OS_TYPE="ubuntu"
OS_VERSION="24.04"
OS_CODENAME="noble"
OS_DISPLAY="Ubuntu 24.04 LTS"
;;
ubuntu2204)
OS_TYPE="ubuntu"
OS_VERSION="22.04"
OS_CODENAME="jammy"
OS_DISPLAY="Ubuntu 22.04 LTS"
;;
esac
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
else
exit_script exit_script
fi fi
case $OS_CHOICE in
debian13)
OS_TYPE="debian"
OS_VERSION="13"
OS_CODENAME="trixie"
OS_DISPLAY="Debian 13 (Trixie)"
;;
debian12)
OS_TYPE="debian"
OS_VERSION="12"
OS_CODENAME="bookworm"
OS_DISPLAY="Debian 12 (Bookworm)"
;;
ubuntu2604)
OS_TYPE="ubuntu"
OS_VERSION="26.04"
OS_CODENAME="resolute"
OS_DISPLAY="Ubuntu 26.04 LTS"
;;
ubuntu2404)
OS_TYPE="ubuntu"
OS_VERSION="24.04"
OS_CODENAME="noble"
OS_DISPLAY="Ubuntu 24.04 LTS"
;;
ubuntu2204)
OS_TYPE="ubuntu"
OS_VERSION="22.04"
OS_CODENAME="jammy"
OS_DISPLAY="Ubuntu 22.04 LTS"
;;
*)
msg_error "Unsupported OS '${OS_CHOICE}' (expected debian13, debian12, ubuntu2604, ubuntu2404 or ubuntu2204)"
exit 1
;;
esac
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}${OS_DISPLAY}${CL}"
} }
function select_cloud_init() { function select_cloud_init() {
if [ "$OS_TYPE" = "ubuntu" ]; then vm_prompt_cloud_init "root"
USE_CLOUD_INIT="yes"
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}yes (Ubuntu requires Cloud-Init)${CL}"
return
fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" \ # Ubuntu ships only cloud images; without cloud-init there is no way in.
--yesno "Enable Cloud-Init for VM configuration?\n\nCloud-Init allows automatic configuration of:\n- User accounts and passwords\n- SSH keys\n- Network settings (DHCP/Static)\n- DNS configuration\n\nYou can also configure these settings later in Proxmox UI.\n\nNote: Debian without Cloud-Init will use nocloud image with console auto-login." 18 68); then if [ "$OS_TYPE" = "ubuntu" ] && [ "$USE_CLOUD_INIT" != "yes" ]; then
USE_CLOUD_INIT="yes" USE_CLOUD_INIT="yes"
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}yes${CL}" export CLOUDINIT_ENABLE="yes"
else msg_warn "Ubuntu requires Cloud-Init - enabling it anyway"
USE_CLOUD_INIT="no"
echo -e "${CLOUD:-${TAB}☁️${TAB}${CL}}${BOLD}${DGN}Cloud-Init: ${BGN}no${CL}"
fi fi
} }
@@ -134,16 +129,14 @@ function get_image_url() {
# SETTINGS FUNCTIONS # SETTINGS FUNCTIONS
# ============================================================================== # ==============================================================================
function default_settings() { function default_settings() {
vm_apply_machine_type "q35"
select_os select_os
select_cloud_init select_cloud_init
VMID=$(get_valid_nextid) VMID=$(get_valid_nextid)
FORMAT=""
if [ "$ARCH" = "arm64" ]; then if [ "$ARCH" = "arm64" ]; then
MACHINE=""
CPU_TYPE="" CPU_TYPE=""
else else
MACHINE=" -machine q35"
CPU_TYPE=" -cpu host" CPU_TYPE=" -cpu host"
fi fi
DISK_CACHE="" DISK_CACHE=""
@@ -158,252 +151,29 @@ function default_settings() {
START_VM="yes" START_VM="yes"
METHOD="default" METHOD="default"
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}" vm_echo_default_settings
if [ "$ARCH" = "arm64" ]; then
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}virt (ARM64)${CL}"
else
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
fi
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}$([ "$ARCH" = "arm64" ] && echo "Default" || echo "Host")${CL}"
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above settings${CL}"
} }
function advanced_settings() { function advanced_settings() {
METHOD="advanced"
select_os select_os
select_cloud_init select_cloud_init
vm_prompt_vmid "${VMID:-$(get_valid_nextid)}"
vm_prompt_machine_type "q35"
vm_prompt_disk_size "10G"
vm_prompt_disk_cache "none"
vm_prompt_hostname "docker"
vm_prompt_cpu_model "host"
vm_prompt_cpu_cores "2"
vm_prompt_ram "4096"
vm_prompt_bridge "vmbr0"
vm_prompt_mac "$GEN_MAC"
vm_prompt_vlan
vm_prompt_mtu
vm_prompt_verbose "no"
vm_prompt_start_vm "yes"
# SSH Key selection for Cloud-Init VMs if vm_confirm_advanced_settings "Ready to create a Docker VM?"; then
if [ "$USE_CLOUD_INIT" = "yes" ]; then
configure_cloudinit_ssh_keys || true
fi
METHOD="advanced"
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid)
# VM ID
while true; do
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VMID" ]; then
VMID=$(get_valid_nextid)
fi
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
sleep 2
continue
fi
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
break
else
exit_script
fi
done
# Machine Type
if [ "$ARCH" = "arm64" ]; then
FORMAT=""
MACHINE=""
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}virt${CL}"
elif MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
"q35" "Q35 (Modern, PCIe)" ON \
"i440fx" "i440fx (Legacy, PCI)" OFF \
3>&1 1>&2 2>&3); then
if [ $MACH = q35 ]; then
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}Q35 (Modern)${CL}"
FORMAT=""
MACHINE=" -machine q35"
else
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx (Legacy)${CL}"
FORMAT=",efitype=4m"
MACHINE=""
fi
else
exit_script
fi
# Disk Size
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
DISK_SIZE="${DISK_SIZE}G"
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
else
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
exit_script
fi
else
exit_script
fi
# Disk Cache
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
"0" "None (Default)" ON \
"1" "Write Through" OFF \
3>&1 1>&2 2>&3); then
if [ $DISK_CACHE = "1" ]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
DISK_CACHE="cache=writethrough,"
else
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
DISK_CACHE=""
fi
else
exit_script
fi
# Hostname
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 docker --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VM_NAME ]; then
HN="docker"
else
HN=$(echo "${VM_NAME,,}" | tr -cs 'a-z0-9-' '-' | sed 's/^-//;s/-$//')
if [ "$HN" != "${VM_NAME,,}" ]; then
whiptail --backtitle "Proxmox VE Helper Scripts" --title "HOSTNAME ADJUSTED" --msgbox "Invalid characters detected. Hostname has been adjusted to:\n\n $HN" 10 58
fi
fi
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
exit_script
fi
# CPU Model
if [ "$ARCH" = "arm64" ]; then
CPU_TYPE=""
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Default${CL}"
elif CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
"1" "Host (Recommended)" ON \
"0" "KVM64" OFF \
3>&1 1>&2 2>&3); then
if [ $CPU_TYPE1 = "1" ]; then
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
CPU_TYPE=" -cpu host"
else
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
CPU_TYPE=""
fi
else
exit_script
fi
# CPU Cores
while true; do
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$CORE_COUNT" ]; then CORE_COUNT="2"; fi
if [[ "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "CPU Cores must be a positive integer (e.g., 2)." 8 58
else
exit_script
fi
done
# RAM Size
while true; do
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 4096 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$RAM_SIZE" ]; then RAM_SIZE="4096"; fi
if [[ "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "RAM Size must be a positive integer in MiB (e.g., 4096)." 8 58
else
exit_script
fi
done
# Bridge
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $BRG ]; then
BRG="vmbr0"
fi
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
else
exit_script
fi
# MAC Address
while true; do
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MAC1" ]; then
MAC="$GEN_MAC"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
break
fi
if [[ "$MAC1" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then
MAC="$MAC1"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "Invalid MAC address format. Use XX:XX:XX:XX:XX:XX (e.g., AA:BB:CC:DD:EE:FF)." 8 58
else
exit_script
fi
done
# VLAN
while true; do
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan (leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VLAN1" ]; then
VLAN1="Default"
VLAN=""
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
break
fi
if [[ "$VLAN1" =~ ^[0-9]+$ ]] && [ "$VLAN1" -ge 1 ] && [ "$VLAN1" -le 4094 ]; then
VLAN=",tag=$VLAN1"
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "VLAN must be a number between 1 and 4094, or leave blank for default." 8 58
else
exit_script
fi
done
# MTU
while true; do
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MTU1" ]; then
MTU1="Default"
MTU=""
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
break
fi
if [[ "$MTU1" =~ ^[0-9]+$ ]] && [ "$MTU1" -ge 576 ] && [ "$MTU1" -le 65520 ]; then
MTU=",mtu=$MTU1"
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "MTU Size must be a number between 576 and 65520, or leave blank for default." 8 58
else
exit_script
fi
done
# Start VM
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
START_VM="yes"
else
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
START_VM="no"
fi
# Confirm
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Docker VM?" --no-button Do-Over 10 58); then
echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above advanced settings${CL}" echo -e "${CREATING}${BOLD}${DGN}Creating a Docker VM using the above advanced settings${CL}"
else else
header_info header_info
@@ -412,81 +182,27 @@ function advanced_settings() {
fi fi
} }
function start_script() {
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
default_settings
else
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
advanced_settings
fi
}
# ============================================================================== # ==============================================================================
# MAIN EXECUTION # MAIN EXECUTION
# ============================================================================== # ==============================================================================
header_info header_info
check_root vm_preflight
arch_check
pve_check
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Docker VM" --yesno "This will create a New Docker VM. Proceed?" 10 58; then vm_start_script "Use Default Settings?" 10 58
:
else
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
start_script
post_to_api_vm post_to_api_vm
# ============================================================================== # ==============================================================================
# STORAGE SELECTION # STORAGE SELECTION
# ============================================================================== # ==============================================================================
msg_info "Validating Storage" vm_select_storage "$HN"
while read -r line; do
TAG=$(echo $line | awk '{print $1}')
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
fi
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
msg_error "Unable to detect a valid storage location."
exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
STORAGE=${STORAGE_MENU[0]}
else
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
printf "\e[?25h"
while [ -z "${STORAGE:+x}" ]; do
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
16 $(($MSG_MAX_LENGTH + 23)) 6 \
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
# ============================================================================== # ==============================================================================
# PREREQUISITES # PREREQUISITES
# ============================================================================== # ==============================================================================
if ! command -v virt-customize &>/dev/null; then vm_ensure_virt_customize
msg_info "Installing libguestfs-tools" $STD apt-get -qq install lsb-release dhcpcd-base -y 2>/dev/null || true
apt-get -qq update >/dev/null
apt-get -qq install libguestfs-tools lsb-release -y >/dev/null
apt-get -qq install dhcpcd-base -y >/dev/null 2>&1 || true
msg_ok "Installed libguestfs-tools"
fi
# ============================================================================== # ==============================================================================
# IMAGE DOWNLOAD # IMAGE DOWNLOAD
@@ -498,13 +214,8 @@ CACHE_FILE="$CACHE_DIR/$(basename "$URL")"
mkdir -p "$CACHE_DIR" mkdir -p "$CACHE_DIR"
msg_ok "${CL}${BL}${URL}${CL}" msg_ok "${CL}${BL}${URL}${CL}"
if [[ ! -s "$CACHE_FILE" ]]; then MIN_IMAGE_BYTES=$((100 * 1024 * 1024))
curl -f#SL -o "$CACHE_FILE" "$URL" vm_fetch_image "$URL" "$CACHE_FILE" --cache --min-bytes "$MIN_IMAGE_BYTES" || exit 115
echo -en "\e[1A\e[0K"
msg_ok "Downloaded ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
else
msg_ok "Using cached image ${CL}${BL}$(basename "$CACHE_FILE")${CL}"
fi
# ============================================================================== # ==============================================================================
# STORAGE TYPE DETECTION # STORAGE TYPE DETECTION
@@ -539,6 +250,13 @@ msg_info "Preparing ${OS_DISPLAY} image with Docker"
WORK_FILE=$(mktemp --suffix=.qcow2) WORK_FILE=$(mktemp --suffix=.qcow2)
cp "$CACHE_FILE" "$WORK_FILE" cp "$CACHE_FILE" "$WORK_FILE"
# qm resize only grows the block device. Without cloud-init nothing grows the
# guest partition, so expand the working copy offline first.
if [ "${USE_CLOUD_INIT:-no}" != "yes" ]; then
msg_info "Expanding the root filesystem to ${DISK_SIZE}"
vm_expand_image "$WORK_FILE" "$DISK_SIZE" || true
fi
export LIBGUESTFS_BACKEND_SETTINGS=dns=8.8.8.8,1.1.1.1 export LIBGUESTFS_BACKEND_SETTINGS=dns=8.8.8.8,1.1.1.1
DOCKER_PREINSTALLED="no" DOCKER_PREINSTALLED="no"
@@ -577,9 +295,7 @@ fi
msg_info "Finalizing image (hostname, SSH config)" msg_info "Finalizing image (hostname, SSH config)"
# Set hostname and prepare for unique machine-id # Set hostname and prepare for unique machine-id
virt-customize -q -a "$WORK_FILE" --hostname "${HN}" >/dev/null 2>&1 || true vm_prepare_cloud_image "$WORK_FILE" "$HN" || true
virt-customize -q -a "$WORK_FILE" --run-command "truncate -s 0 /etc/machine-id" >/dev/null 2>&1 || true
virt-customize -q -a "$WORK_FILE" --run-command "rm -f /var/lib/dbus/machine-id" >/dev/null 2>&1 || true
# Configure SSH for Cloud-Init # Configure SSH for Cloud-Init
if [ "$USE_CLOUD_INIT" = "yes" ]; then if [ "$USE_CLOUD_INIT" = "yes" ]; then
@@ -716,16 +432,17 @@ msg_ok "Attached EFI and root disk"
set_description set_description
# Cloud-Init configuration # Cloud-Init configuration
if [ "$USE_CLOUD_INIT" = "yes" ]; then msg_info "Configuring Cloud-Init"
msg_info "Configuring Cloud-Init" if vm_provision "$VMID"; then
setup_cloud_init "$VMID" "$STORAGE" "$HN" "yes"
msg_ok "Cloud-Init configured" msg_ok "Cloud-Init configured"
else
msg_warn "VM created, but not provisioned"
fi fi
# Start VM # Start VM
if [ "$START_VM" == "yes" ]; then if [ "$START_VM" == "yes" ]; then
msg_info "Starting Docker VM" msg_info "Starting Docker VM"
qm start $VMID >/dev/null 2>&1 $STD qm start $VMID
msg_ok "Started Docker VM" msg_ok "Started Docker VM"
fi fi

View File

@@ -1,289 +1,55 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Copyright (c) 2021-2026 tteck # Copyright (c) 2021-2026 tteck
# Author: tteck (tteckster) # Author: tteck (tteckster) | MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
source /dev/stdin <<<$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) COMMUNITY_SCRIPTS_URL="${COMMUNITY_SCRIPTS_URL:-https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main}"
source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/pve/vm-core.func")
load_functions
function header_info {
clear
cat <<"EOF"
__ __ ___ _ __ __ ____ _____
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / __ \/ ___/
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / /\__ \
/ __ / /_/ / / / / / / __/ / ___ |(__ |__ ) (__ ) /_/ /_/ / / / / /_ / /_/ /___/ /
/_/ /_/\____/_/ /_/ /_/\___/ /_/ |_/____/____/_/____/\__/\__,_/_/ /_/\__/ \____//____/
EOF
}
header_info
echo -e "\n Loading..."
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//') GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)"
VERSIONS=(stable beta dev)
METHOD="" METHOD=""
APP="Home Assistant OS"
APP_TYPE="vm"
NSAPP="haos-vm" NSAPP="haos-vm"
var_os="homeassistant" var_os="homeassistant"
DISK_SIZE="32G" DISK_SIZE="32G"
for version in "${VERSIONS[@]}"; do for channel in stable beta dev; do
eval "$version=$(curl -fsSL https://raw.githubusercontent.com/home-assistant/version/master/stable.json | grep '"ova"' | cut -d '"' -f 4)" channel_version=$(curl -fsSL "https://raw.githubusercontent.com/home-assistant/version/master/${channel}.json" | grep '"ova"' | cut -d '"' -f 4) || channel_version=""
printf -v "$channel" '%s' "$channel_version"
done done
YW=$(echo "\033[33m") if [ -z "$stable" ]; then
BL=$(echo "\033[36m") echo -e "Could not determine the current Home Assistant OS release."
exit 1
fi
beta="${beta:-$stable}"
dev="${dev:-$stable}"
HA=$(echo "\033[1;34m") HA=$(echo "\033[1;34m")
RD=$(echo "\033[01;31m")
BGN=$(echo "\033[4;92m")
GN=$(echo "\033[1;92m")
DGN=$(echo "\033[32m")
CL=$(echo "\033[m")
BOLD=$(echo "\033[1m")
BFR="\\r\\033[K"
HOLD=" "
TAB=" "
CM="${TAB}✔️${TAB}${CL}"
CROSS="${TAB}✖️${TAB}${CL}"
INFO="${TAB}💡${TAB}${CL}"
OS="${TAB}🖥️${TAB}${CL}"
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
DISKSIZE="${TAB}💾${TAB}${CL}"
CPUCORE="${TAB}🧠${TAB}${CL}"
RAMSIZE="${TAB}🛠️${TAB}${CL}"
CONTAINERID="${TAB}🆔${TAB}${CL}"
HOSTNAME="${TAB}🏠${TAB}${CL}"
BRIDGE="${TAB}🌉${TAB}${CL}"
GATEWAY="${TAB}🌐${TAB}${CL}"
DEFAULT="${TAB}⚙️${TAB}${CL}"
MACADDRESS="${TAB}🔗${TAB}${CL}"
VLANTAG="${TAB}🏷️${TAB}${CL}"
CREATING="${TAB}🚀${TAB}${CL}"
ADVANCED="${TAB}🧩${TAB}${CL}"
CLOUD="${TAB}☁️${TAB}${CL}"
THIN="discard=on,ssd=1," THIN="discard=on,ssd=1,"
header_info
echo -e "\n Loading..."
set -e set -e
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
trap cleanup EXIT trap cleanup EXIT
trap 'post_update_to_api "failed" "130"' SIGINT trap 'post_update_to_api "failed" "130"' SIGINT
trap 'post_update_to_api "failed" "143"' SIGTERM trap 'post_update_to_api "failed" "143"' SIGTERM
trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP trap 'post_update_to_api "failed" "129"; exit 129' SIGHUP
function error_handler() {
local exit_code="$?"
local line_number="$1"
local command="$2"
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
post_update_to_api "failed" "${exit_code}"
echo -e "\n$error_message\n"
cleanup_vmid
}
function get_valid_nextid() {
local try_id
try_id=$(pvesh get /cluster/nextid)
while true; do
if [ -f "/etc/pve/qemu-server/${try_id}.conf" ] || [ -f "/etc/pve/lxc/${try_id}.conf" ]; then
try_id=$((try_id + 1))
continue
fi
if lvs --noheadings -o lv_name | grep -qE "(^|[-_])${try_id}($|[-_])"; then
try_id=$((try_id + 1))
continue
fi
break
done
echo "$try_id"
}
function cleanup_vmid() {
if qm status $VMID &>/dev/null; then
qm stop $VMID &>/dev/null
qm destroy $VMID &>/dev/null
fi
}
function cleanup() {
local exit_code=$?
popd >/dev/null
# Only send telemetry if post_to_api_vm was called (installing status was sent)
if [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
if [[ $exit_code -eq 0 ]]; then
post_update_to_api "done" "none"
else
post_update_to_api "failed" "$exit_code"
fi
fi
rm -rf $TEMP_DIR
}
TEMP_DIR=$(mktemp -d) TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null pushd $TEMP_DIR >/dev/null
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Homeassistant OS VM" --yesno "This will create a New Homeassistant OS VM. Proceed?" 10 58; then
:
else
header_info && echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
fi
function msg_info() {
local msg="$1"
echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
}
function msg_ok() {
local msg="$1"
echo -e "${BFR}${CM}${GN}${msg}${CL}"
}
function msg_error() {
local msg="$1"
echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
}
function check_root() {
if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
clear
msg_error "Please run this script as root."
echo -e "\nExiting..."
sleep 2
exit
fi
}
# 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, 9.0 and 9.2
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.0 and 9.2
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
local MINOR="${BASH_REMATCH[1]}"
if ((MINOR < 0 || MINOR > 2)); then
msg_error "This version of Proxmox VE is not supported."
msg_error "Supported: Proxmox VE version 9.0 9.2"
exit 105
fi
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.x or 9.0 9.2"
exit 105
}
function arch_check() {
if [ "$(dpkg --print-architecture)" != "amd64" ]; then
echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
echo -e "Exiting..."
sleep 2
exit
fi
}
function ssh_check() {
if command -v pveversion >/dev/null 2>&1; then
if [ -n "${SSH_CLIENT:+x}" ]; then
if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
echo "you've been warned"
else
clear
exit
fi
fi
fi
}
function exit-script() {
clear
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
exit
}
# Ensure pv is installed or abort with instructions
function ensure_pv() {
if ! command -v pv &>/dev/null; then
msg_info "Installing required package: pv"
if ! apt-get update -qq &>/dev/null || ! apt-get install -y pv &>/dev/null; then
msg_error "Failed to install pv automatically."
echo -e "\nPlease run manually on the Proxmox host:\n apt install pv\n"
exit 237
fi
msg_ok "Installed pv"
fi
}
# Download an .xz file and validate it
# Args: $1=url $2=cache_file
function download_and_validate_xz() {
local url="$1"
local file="$2"
# If file exists, check validity
if [[ -s "$file" ]]; then
if xz -t "$file" &>/dev/null; then
msg_ok "Using cached image $(basename "$file")"
return 0
else
msg_error "Cached file $(basename "$file") is corrupted. Deleting and retrying download..."
rm -f "$file"
fi
fi
# Download fresh file
msg_info "Downloading image: $(basename "$file")"
if ! curl -fSL -o "$file" "$url"; then
msg_error "Download failed: $url"
rm -f "$file"
exit 115
fi
# Validate again
if ! xz -t "$file" &>/dev/null; then
msg_error "Downloaded file $(basename "$file") is corrupted. Please try again later."
rm -f "$file"
exit 115
fi
msg_ok "Downloaded and validated $(basename "$file")"
}
# Extract .xz with pv
# Args: $1=cache_file $2=target_img
function extract_xz_with_pv() {
set -o pipefail
local file="$1"
local target="$2"
msg_info "Decompressing $(basename "$file") to $target"
if ! xz -dc "$file" | pv -N "Extracting" >"$target"; then
msg_error "Failed to extract $file"
rm -f "$target"
exit 115
fi
msg_ok "Decompressed to $target"
}
function default_settings() { function default_settings() {
BRANCH="$stable" BRANCH="$stable"
var_version="${BRANCH}"
VMID=$(get_valid_nextid) VMID=$(get_valid_nextid)
MACHINE=" -machine q35" vm_apply_machine_type "q35"
FORMAT=""
DISK_SIZE="32G" DISK_SIZE="32G"
HN="haos-${BRANCH}" DISK_CACHE=""
HN="homeassistant"
CPU_TYPE="" CPU_TYPE=""
CORE_COUNT="2" CORE_COUNT="2"
RAM_SIZE="4096" RAM_SIZE="4096"
@@ -293,297 +59,52 @@ function default_settings() {
MTU="" MTU=""
START_VM="yes" START_VM="yes"
METHOD="default" METHOD="default"
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}" vm_echo_default_settings
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
echo -e "${CREATING}${BOLD}${DGN}Creating a Homeassistant OS VM using the above default settings${CL}"
} }
function advanced_settings() { function advanced_settings() {
METHOD="advanced" METHOD="advanced"
if BRANCH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Homeassistant OS Version" --radiolist "Choose Version" --cancel-button Exit-Script 10 58 3 \ if vm_dialog radiolist "Homeassistant OS Version" --cancel-button Exit-Script "Choose Version" 10 58 3 \
"$stable" "Stable " ON \ "$stable" "Stable " ON \
"$beta" "Beta " OFF \ "$beta" "Beta " OFF \
"$dev" "Dev " OFF \ "$dev" "Dev " OFF; then
3>&1 1>&2 2>&3); then BRANCH="$VM_DIALOG_RESULT"
var_version="${BRANCH}" var_version="${BRANCH}"
echo -e "${DGN}Using HAOS Version: ${BGN}$BRANCH${CL}" echo -e "${DGN}Using HAOS Version: ${BGN}$BRANCH${CL}"
else else
exit-script exit_script
fi fi
[ -z "${VMID:-}" ] && VMID=$(get_valid_nextid) vm_prompt_vmid "${VMID:-$(get_valid_nextid)}"
while true; do vm_prompt_machine_type "q35"
if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $VMID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then vm_prompt_disk_size "$DISK_SIZE" "Set Disk Size in GiB (e.g., 10, 20)"
if [ -z "$VMID" ]; then vm_prompt_disk_cache "writethrough"
VMID=$(get_valid_nextid) vm_prompt_hostname "homeassistant"
fi vm_prompt_cpu_model "kvm64"
if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then vm_prompt_cpu_cores "2"
echo -e "${CROSS}${RD} ID $VMID is already in use${CL}" vm_prompt_ram "4096"
sleep 2 vm_prompt_bridge "vmbr0"
continue vm_prompt_mac "$GEN_MAC"
fi vm_prompt_vlan
echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}" vm_prompt_mtu
break vm_prompt_verbose "no"
else vm_prompt_start_vm "yes"
exit-script
fi
done
if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Machine Type" 10 58 2 \ if vm_confirm_advanced_settings "Ready to create Homeassistant OS ${BRANCH} VM?"; then
"q35" "Modern (PCIe, UEFI, default)" ON \ echo -e "${CREATING}${BOLD}${DGN}Creating a Homeassistant OS VM using the above advanced settings${CL}"
"i440fx" "Legacy (older compatibility)" OFF \
3>&1 1>&2 2>&3); then
if [ "$MACH" = "q35" ]; then
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}q35${CL}"
FORMAT=""
MACHINE=" -machine q35"
else
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
FORMAT=",efitype=4m"
MACHINE=""
fi
else
exit-script
fi
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
DISK_SIZE="${DISK_SIZE}G"
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
else
echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
exit-script
fi
else
exit-script
fi
if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
"0" "None" OFF \
"1" "Write Through (Default)" ON \
3>&1 1>&2 2>&3); then
if [ $DISK_CACHE = "1" ]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
DISK_CACHE="cache=writethrough,"
else
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
DISK_CACHE=""
fi
else
exit-script
fi
if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 haos${BRANCH} --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $VM_NAME ]; then
HN="haos${BRANCH}"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
else
HN=$(echo "${VM_NAME,,}" | tr -cs 'a-z0-9-' '-' | sed 's/^-//;s/-$//')
if [ "$HN" != "${VM_NAME,,}" ]; then
whiptail --backtitle "Proxmox VE Helper Scripts" --title "HOSTNAME ADJUSTED" --msgbox "Invalid characters detected. Hostname has been adjusted to:\n\n $HN" 10 58
fi
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
fi
else
exit-script
fi
if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose CPU Model" --cancel-button Exit-Script 12 74 3 \
"KVM64" "Default - safe for migration/compatibility" ON \
"x86-64-v2-AES" "Wider feature set, needed by newer HA releases (PVE 8+, host CPU 2010+)" OFF \
"Host" "Use host CPU features (faster, no migration)" OFF \
3>&1 1>&2 2>&3); then
case "$CPU_TYPE1" in
Host)
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
CPU_TYPE=" -cpu host"
;;
x86-64-v2-AES)
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}x86-64-v2-AES${CL}"
CPU_TYPE=" -cpu x86-64-v2-AES"
;;
*)
echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
CPU_TYPE=""
;;
esac
else
exit-script
fi
while true; do
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$CORE_COUNT" ]; then CORE_COUNT="2"; fi
if [[ "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "CPU Cores must be a positive integer (e.g., 2)." 8 58
else
exit-script
fi
done
while true; do
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$RAM_SIZE" ]; then RAM_SIZE="4096"; fi
if [[ "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "RAM Size must be a positive integer in MiB (e.g., 4096)." 8 58
else
exit-script
fi
done
if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z $BRG ]; then
BRG="vmbr0"
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
else
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
fi
else
exit-script
fi
while true; do
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MAC1" ]; then
MAC="$GEN_MAC"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
break
fi
if [[ "$MAC1" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then
MAC="$MAC1"
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "Invalid MAC address format. Use XX:XX:XX:XX:XX:XX (e.g., AA:BB:CC:DD:EE:FF)." 8 58
else
exit-script
fi
done
while true; do
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan (leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$VLAN1" ]; then
VLAN1="Default"
VLAN=""
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
break
fi
if [[ "$VLAN1" =~ ^[0-9]+$ ]] && [ "$VLAN1" -ge 1 ] && [ "$VLAN1" -le 4094 ]; then
VLAN=",tag=$VLAN1"
echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "VLAN must be a number between 1 and 4094, or leave blank for default." 8 58
else
exit-script
fi
done
while true; do
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [ -z "$MTU1" ]; then
MTU1="Default"
MTU=""
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
break
fi
if [[ "$MTU1" =~ ^[0-9]+$ ]] && [ "$MTU1" -ge 576 ] && [ "$MTU1" -le 65520 ]; then
MTU=",mtu=$MTU1"
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
break
fi
whiptail --backtitle "Proxmox VE Helper Scripts" --title "INVALID INPUT" --msgbox "MTU Size must be a number between 576 and 65520, or leave blank for default." 8 58
else
exit-script
fi
done
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
echo -e "${DGN}Start VM when completed: ${BGN}yes${CL}"
START_VM="yes"
else
echo -e "${DGN}Start VM when completed: ${BGN}no${CL}"
START_VM="no"
fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create Homeassistant OS ${BRANCH} VM?" --no-button Do-Over 10 58); then
echo -e "${RD}Creating a Homeassistant OS VM using the above advanced settings${CL}"
else else
header_info header_info
echo -e "${RD}Using Advanced Settings${CL}" echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
advanced_settings advanced_settings
fi fi
} }
function start_script() {
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
header_info
echo -e "${BL}Using Default Settings${CL}"
default_settings
else
header_info
echo -e "${RD}Using Advanced Settings${CL}"
advanced_settings
fi
}
check_root vm_preflight
arch_check vm_start_script "Use Default Settings?" 10 58
pve_check
ssh_check
ensure_pv
start_script
post_to_api_vm post_to_api_vm
msg_info "Validating Storage" vm_select_storage "$HN"
while read -r line; do
TAG=$(echo $line | awk '{print $1}')
TYPE=$(echo $line | awk '{printf "%-10s", $2}')
FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
fi
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content images | awk 'NR>1')
VALID=$(pvesm status -content images | awk 'NR>1')
if [ -z "$VALID" ]; then
msg_error "Unable to detect a valid storage location."
exit
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
STORAGE=${STORAGE_MENU[0]}
else
while [ -z "${STORAGE:+x}" ]; do
if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
printf "\e[?25h"
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
"Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
16 $(($MSG_MAX_LENGTH + 23)) 6 \
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
done
fi
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
var_version="${BRANCH}" var_version="${BRANCH}"
msg_info "Retrieving the URL for Home Assistant ${BRANCH} Disk Image" msg_info "Retrieving the URL for Home Assistant ${BRANCH} Disk Image"
@@ -593,14 +114,10 @@ else
URL="https://github.com/home-assistant/operating-system/releases/download/${BRANCH}/haos_ova-${BRANCH}.qcow2.xz" URL="https://github.com/home-assistant/operating-system/releases/download/${BRANCH}/haos_ova-${BRANCH}.qcow2.xz"
fi fi
CACHE_DIR="/var/lib/vz/template/cache" CACHE_FILE="$(vm_image_cache_path "$URL")"
CACHE_FILE="$CACHE_DIR/$(basename "$URL")"
FILE_IMG="/var/lib/vz/template/tmp/${CACHE_FILE##*/%.xz}" # .qcow2
mkdir -p "$CACHE_DIR" "$(dirname "$FILE_IMG")"
msg_ok "${CL}${BL}${URL}${CL}" msg_ok "${CL}${BL}${URL}${CL}"
download_and_validate_xz "$URL" "$CACHE_FILE" vm_fetch_image "$URL" "$CACHE_FILE" --cache --verify-xz || exit 115
msg_info "Creating Home Assistant OS VM shell" msg_info "Creating Home Assistant OS VM shell"
qm create $VMID${MACHINE} -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \ qm create $VMID${MACHINE} -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE} \
@@ -608,7 +125,8 @@ qm create $VMID${MACHINE} -bios ovmf -agent 1 -tablet 0 -localtime 1 ${CPU_TYPE}
-net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null -net0 "virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU" -onboot 1 -ostype l26 -scsihw virtio-scsi-pci >/dev/null
msg_ok "Created VM shell" msg_ok "Created VM shell"
extract_xz_with_pv "$CACHE_FILE" "$FILE_IMG" vm_extract_image "$CACHE_FILE" || exit 115
FILE_IMG="$VM_IMAGE_FILE"
msg_info "Importing disk into storage ($STORAGE)" msg_info "Importing disk into storage ($STORAGE)"
if qm disk import --help >/dev/null 2>&1; then if qm disk import --help >/dev/null 2>&1; then
@@ -637,54 +155,20 @@ qm set $VMID \
qm set $VMID --agent enabled=1 >/dev/null qm set $VMID --agent enabled=1 >/dev/null
msg_ok "Attached EFI and root disk" msg_ok "Attached EFI and root disk"
msg_info "Resizing disk to $DISK_SIZE" vm_resize_disk
qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
msg_ok "Resized disk"
DESCRIPTION=$( set_description
cat <<EOF
<div align='center'>
<a href='https://community-scripts.org' target='_blank' rel='noopener noreferrer'>
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
</a>
<h2 style='font-size: 24px; margin: 20px 0;'>Homeassistant OS VM</h2>
<p style='margin: 16px 0;'>
<a href='https://ko-fi.com/community_scripts' target='_blank' rel='noopener noreferrer'>
<img src='https://img.shields.io/badge/&#x2615;-Buy us a coffee-blue' alt='spend Coffee' />
</a>
</p>
<span style='margin: 0 10px;'>
<i class="fa fa-github fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-comments fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
</span>
<span style='margin: 0 10px;'>
<i class="fa fa-exclamation-circle fa-fw" style="color: #f5f5f5;"></i>
<a href='https://github.com/community-scripts/ProxmoxVE/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
</span>
</div>
EOF
)
qm set $VMID -description "$DESCRIPTION" >/dev/null
msg_ok "Created Homeassistant OS VM ${CL}${BL}(${HN})" msg_ok "Created Homeassistant OS VM ${CL}${BL}(${HN})"
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Image Cache" \ # vm_fetch_image --cache keeps it, as it does for every other VM script.
--yesno "Keep downloaded Home Assistant OS image for future VMs?\n\nFile: $CACHE_FILE" 10 70; then if [[ "${VM_KEEP_IMAGE:-yes}" != "yes" ]]; then
msg_ok "Keeping cached image"
else
rm -f "$CACHE_FILE" rm -f "$CACHE_FILE"
msg_ok "Deleted cached image" msg_ok "Deleted cached image"
fi fi
if [ "$START_VM" == "yes" ]; then if [ "$START_VM" == "yes" ]; then
msg_info "Starting Home Assistant OS VM" msg_info "Starting Home Assistant OS VM"
qm start $VMID $STD qm start $VMID
msg_ok "Started Home Assistant OS VM" msg_ok "Started Home Assistant OS VM"
fi fi
post_update_to_api "done" "none" post_update_to_api "done" "none"