Compare commits

...

42 Commits

Author SHA1 Message Date
CanbiZ (MickLesk) 27190a1fcc Update script messages for GitLab installation 2026-08-10 08:47:09 +02:00
push-app-to-main[bot] ec74ef5be6 Add gitlab (ct) 2026-08-10 06:36:24 +00:00
community-scripts-pr-app[bot] 6ae19c8a22 Update CHANGELOG.md (#16381)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-10 00:05:16 +00:00
push-app-to-main[bot] d734d2204f Add post-pdm-install (pve) (#16368)
Co-authored-by: push-app-to-main[bot] <203845782+push-app-to-main[bot]@users.noreply.github.com>
2026-08-10 10:04:51 +10:00
community-scripts-pr-app[bot] 43e3f5215d Update CHANGELOG.md (#16378)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 18:23:08 +00:00
CanbiZ (MickLesk) 3ed946390f Portainer: Update existing CE and BE installations (#16357) 2026-08-09 20:22:40 +02:00
community-scripts-pr-app[bot] 4626ec8845 Update CHANGELOG.md (#16377)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 18:09:09 +00:00
fudian 579c1b6b26 Fix: CouchDB Erlang cookie breaks vm.args (use hex) (#16361)
* CouchDB: generate an Erlang-safe (hex) cookie

ERLANG_COOKIE was generated with `openssl rand -base64 32`, whose output
contains +, / and = (e.g. "+w2dDazB/CrIZMsZu8edX4hn55QeRXOCi+hom25Lmm8=").
CouchDB writes the cookie into /opt/couchdb/etc/vm.args as
`-setcookie '<cookie>'`, and those characters break Erlang's vm.args
parsing, so couchdb.service fails to start on a fresh install (#16360).

Use `openssl rand -hex 32` instead: a 64-char hex string is alphanumeric,
needs no quoting, and is always a valid Erlang cookie. (Same 256-bit
entropy as the base64 of 32 bytes.)

Closes #16360

* Update install/apache-couchdb-install.sh

---------

Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-08-09 20:08:41 +02:00
community-scripts-pr-app[bot] 5264fc5897 Update CHANGELOG.md (#16374)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 16:50:47 +00:00
community-scripts-pr-app[bot] 6063f0747d Update CHANGELOG.md (#16373)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 16:50:32 +00:00
CanbiZ (MickLesk) 5374826753 SparkyFitness: Install Git for frontend builds (#16352) 2026-08-09 18:50:22 +02:00
community-scripts-pr-app[bot] b32071de43 Update CHANGELOG.md (#16372)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 16:50:12 +00:00
CanbiZ (MickLesk) af10e10f20 Byparr: Use invisible-playwright browser setup (#16353) 2026-08-09 18:50:05 +02:00
CanbiZ (MickLesk) ad09299de7 Crafty Controller: Restore ownership after updates (#16354) 2026-08-09 18:49:50 +02:00
community-scripts-pr-app[bot] 5f71caac5b Update CHANGELOG.md (#16371)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 16:49:48 +00:00
CanbiZ (MickLesk) 87db412709 Webtrees: Fix schema check in silent mode (#16355) 2026-08-09 18:49:38 +02:00
CanbiZ (MickLesk) 83ad1c972d SigNoz: Allow legacy metadata schema on ClickHouse 26 (#16356) 2026-08-09 18:49:26 +02:00
community-scripts-pr-app[bot] d11d3156db Update CHANGELOG.md (#16369)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 14:19:55 +00:00
CanbiZ (MickLesk) 773b46c969 github: update Star History links and image sources (#16367) 2026-08-09 16:19:29 +02:00
community-scripts-pr-app[bot] d87e59f626 Update CHANGELOG.md (#16363)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 00:07:00 +00:00
community-scripts-pr-app[bot] d69579d477 Archive old changelog entries (#16362)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 00:06:30 +00:00
community-scripts-pr-app[bot] 8386465a92 Update CHANGELOG.md (#16338)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-08 02:38:26 +00:00
push-app-to-main[bot] bcec3c405a Ignis (#16330)
* Add ignis (ct)

* Fix source line to always use community scripts URL

Updated the source line to always fetch from the community scripts repository.

* Apply suggestion from @tremor021

---------

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>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-08-08 12:37:57 +10:00
community-scripts-pr-app[bot] 4c8f5bd1f0 Update CHANGELOG.md (#16337)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-08 02:35:25 +00:00
CanbiZ (MickLesk) d87fef0892 core - setup_nodejs: bypass npm allowScripts policy globally on npm >=11 (#16280)
* setup_nodejs: bypass npm allowScripts policy globally on npm >=11

* Update misc/tools.func

Co-authored-by: Sam Heinz <sam@samheinz.com>

---------

Co-authored-by: Sam Heinz <sam@samheinz.com>
2026-08-08 12:35:03 +10:00
community-scripts-pr-app[bot] 5d14989682 Update CHANGELOG.md (#16334)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 17:46:02 +00:00
Tom Frenzel a296ccfc7e HortusFox: start applying db migrations (#16324) 2026-08-07 19:45:32 +02:00
community-scripts-pr-app[bot] f0fc577d79 Update CHANGELOG.md (#16333)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 17:43:02 +00:00
push-app-to-main[bot] fbd9d24966 NetworkOptimizer (#16328)
* Add networkoptimizer (ct)

* Update source line for build.func in networkoptimizer.sh

Updated the source line to always use the latest build.func script from the community scripts repository.

* Apply suggestion from @tremor021

* Apply suggestion from @tremor021

---------

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>
Co-authored-by: Slaviša Arežina <58952836+tremor021@users.noreply.github.com>
2026-08-07 19:42:34 +02:00
community-scripts-pr-app[bot] 347e0e6ff0 Update CHANGELOG.md (#16332)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 17:42:05 +00:00
push-app-to-main[bot] 4adea9666e Orb (#16329)
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
2026-08-07 19:41:33 +02:00
community-scripts-pr-app[bot] 1d94e50601 Update CHANGELOG.md (#16326)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 09:44:04 +00:00
CanbiZ (MickLesk) 0092fa8b54 Docker: report container updates instead of prompting, stop auto-updating Portainer Agent, fix addon detection of legacy Portainer (#16298)
* Docker: report container updates instead of prompting, stop auto-updating Portainer Agent, fix addon detection of legacy Portainer

* Update portainer.sh
2026-08-07 19:43:32 +10:00
community-scripts-pr-app[bot] e00d4c6e51 Update CHANGELOG.md (#16322)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 08:11:07 +00:00
community-scripts-pr-app[bot] c1d5bfdb83 Update CHANGELOG.md (#16321)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 08:10:44 +00:00
CanbiZ (MickLesk) 33de14e45c Immich: retry mise install on transient npm download failures (#16301) 2026-08-07 10:10:35 +02:00
Austin 156f5ae16f changedetection: remove msttcorefonts to fix install hang (#16319) 2026-08-07 10:10:15 +02:00
community-scripts-pr-app[bot] 7100e1679e Update CHANGELOG.md (#16320)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-07 02:50:12 +00:00
CanbiZ (MickLesk) 63e4ea1396 core: extend new vars and pocketbase values (#16313)
* Let docker-install.sh take its three answers up front

The script asked three questions with no way to answer them in advance,
so a Docker container could not be deployed unattended: Portainer, the
Portainer Agent, and whether to expose the TCP socket.

Each now reads a variable and prompts only when it is unset, the same
shape install/forgejo-runner-install.sh already uses:

  var_portainer         yes | no
  var_portainer_agent   yes | no
  var_docker_socket     n | l (127.0.0.1) | a (0.0.0.0)

Interactive behaviour is unchanged — with nothing set, all three still
ask exactly as before.

The matching declaration for the script's PocketBase record, which the
website generator reads to offer these as form fields:

  "app_vars": [
    {"name":"var_portainer","label":"Install Portainer","type":"boolean","default":"no"},
    {"name":"var_portainer_agent","label":"Install Portainer Agent","type":"boolean","default":"no",
     "help":"Only used when Portainer itself is not installed"},
    {"name":"var_docker_socket","label":"Expose Docker TCP socket","type":"select",
     "options":["n","l","a"],"default":"n",
     "help":"l = 127.0.0.1 only, a = all interfaces (insecure)"}
  ]

CONTRIBUTING.md documents the convention so the next script follows it.

* Let docker-install.sh take its three answers up front

The script asked three questions with no way to answer them in advance,
so a Docker container could not be deployed unattended: Portainer, the
Portainer Agent, and whether to expose the TCP socket.

Each now reads a variable and prompts only when it is unset, the same
shape install/forgejo-runner-install.sh already uses:

  var_portainer         yes | no
  var_portainer_agent   yes | no
  var_docker_socket     n | l (127.0.0.1) | a (0.0.0.0)

Interactive behaviour is unchanged — with nothing set, all three still
ask exactly as before.

The matching declaration for the script's PocketBase record, which the
website generator reads to offer these as form fields:

  "app_vars": [
    {"name":"var_portainer","label":"Install Portainer","type":"boolean","default":"no"},
    {"name":"var_portainer_agent","label":"Install Portainer Agent","type":"boolean","default":"no",
     "help":"Only used when Portainer itself is not installed"},
    {"name":"var_docker_socket","label":"Expose Docker TCP socket","type":"select",
     "options":["n","l","a"],"default":"n",
     "help":"l = 127.0.0.1 only, a = all interfaces (insecure)"}
  ]

CONTRIBUTING.md documents the convention so the next script follows it.

* Let forgejo-runner and pangolin take their answers up front

forgejo-runner already exported two of the three values its install
script requires, but not var_forgejo_runner_uuid — so an unattended
install passed the ct-level guard and then stopped at a prompt inside
the container, which is the one place nobody can answer it. The guard
missed it for the same reason.

pangolin asked for its URL and email with no way to supply them. Both
sides are needed: the read in install/ now only fires when the variable
is unset, and ct/ exports it, because lxc-attach carries the caller's
environment but only what was exported.

Reverts the docker change from the previous commit; it is superseded by
work on another branch.

* Teach the PocketBase workflows the capability fields

All three wrote fields the site no longer reads. The slash bot and the
AI bot accepted has_arm=true and github=owner/repo; push-json mapped
has_arm into the payload. After the schema change those writes would
have gone to columns that are not there.

architectures and platforms are multi-selects over a closed set, so
both bots reject an unknown value instead of storing it — the same
guarantee the field type gives in the admin UI.

push-json still reads has_arm when architectures is absent, because
ProxmoxVED's json files carry the old key until they are converted.

* Drop the docker change again

It came back through the merge in 35735dae: the branch was pushed
before the revert, so merging the remote copy restored it. Removing it
forward rather than rewriting history that is already published.
2026-08-07 12:49:45 +10:00
rcourtman 63a91c8d93 fix(tools): stop a failed deploy from wiping the existing install (#16312) 2026-08-06 21:50:12 +02:00
CanbiZ (MickLesk) 590d638094 build.func: fix pveam arch filter for extra whitespace column (#16315) 2026-08-06 21:03:28 +02:00
Sam Heinz fb1d670158 dont skip enterprise repo setup on arm64 (#16307) 2026-08-06 21:02:43 +02:00
41 changed files with 1622 additions and 251 deletions
+139
View File
@@ -1,3 +1,142 @@
## 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))
## 2026-08-06
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- paperless: change update abort message (endless spinner) [@MickLesk](https://github.com/MickLesk) ([#16299](https://github.com/community-scripts/ProxmoxVE/pull/16299))
- #### ✨ New Features
- Vikunja: remove version pin, v2.5.0 fixes the systemd syscall filter crash [@MickLesk](https://github.com/MickLesk) ([#16300](https://github.com/community-scripts/ProxmoxVE/pull/16300))
### 💾 Core
- #### 🔧 Refactor
- build.func: filter templates by host architecture during search [@MickLesk](https://github.com/MickLesk) ([#16302](https://github.com/community-scripts/ProxmoxVE/pull/16302))
## 2026-08-05
### 🚀 Updated Scripts
- #### ✨ New Features
- NextcloudPI: Bump to Debian Trixie & Tweak broken SSH [@MickLesk](https://github.com/MickLesk) ([#15957](https://github.com/community-scripts/ProxmoxVE/pull/15957))
### 🧰 Tools
- #### 🐞 Bug Fixes
- fix(monitor-all): reduce polling CPU overhead [@jomplox](https://github.com/jomplox) ([#15907](https://github.com/community-scripts/ProxmoxVE/pull/15907))
## 2026-08-04
### 🆕 New Scripts
- Hister ([#16259](https://github.com/community-scripts/ProxmoxVE/pull/16259))
- Obsidian-LiveSync ([#16233](https://github.com/community-scripts/ProxmoxVE/pull/16233))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Actual Budget: allow native module install scripts under npm 11 (Node24) [@MickLesk](https://github.com/MickLesk) ([#16277](https://github.com/community-scripts/ProxmoxVE/pull/16277))
- Heimdall-Dashboard: run full composer install on update, force production env [@MickLesk](https://github.com/MickLesk) ([#16278](https://github.com/community-scripts/ProxmoxVE/pull/16278))
- xyOps: rebuild xySat satellite during update [@MickLesk](https://github.com/MickLesk) ([#16279](https://github.com/community-scripts/ProxmoxVE/pull/16279))
- HAOS: remove non-ASCII dash from CPU model dialog text [@MickLesk](https://github.com/MickLesk) ([#16276](https://github.com/community-scripts/ProxmoxVE/pull/16276))
- fix: back up Termix db/data so the update stops destroying encryption keys [@LukeGus](https://github.com/LukeGus) ([#16275](https://github.com/community-scripts/ProxmoxVE/pull/16275))
- passwordpusher: dynamically read Ruby version from .ruby-version file [@Copilot](https://github.com/Copilot) ([#16242](https://github.com/community-scripts/ProxmoxVE/pull/16242))
- fix(salt): write version cache to ~/.salt, not /~.salt [@TowyTowy](https://github.com/TowyTowy) ([#16265](https://github.com/community-scripts/ProxmoxVE/pull/16265))
- AFFiNE: fix version and build type reported by the app itself [@MickLesk](https://github.com/MickLesk) ([#16251](https://github.com/community-scripts/ProxmoxVE/pull/16251))
- Passbolt: fetch GPG key from Passbolt's own host instead of the flaky keyserver [@MickLesk](https://github.com/MickLesk) ([#16248](https://github.com/community-scripts/ProxmoxVE/pull/16248))
- #### ✨ New Features
- Opencloud: Pin version to 7.4.0 [@vhsdream](https://github.com/vhsdream) ([#16257](https://github.com/community-scripts/ProxmoxVE/pull/16257))
- #### 🔧 Refactor
- Bump NodeJS Versions of several scripts [@MickLesk](https://github.com/MickLesk) ([#16230](https://github.com/community-scripts/ProxmoxVE/pull/16230))
### 💾 Core
- #### 🐞 Bug Fixes
- tools.func: never delete ubuntu.sources (or other distro base sources) as orphaned [@MickLesk](https://github.com/MickLesk) ([#16250](https://github.com/community-scripts/ProxmoxVE/pull/16250))
- tools.func: complete a stale/partial backup manifest instead of trusting it as-is [@MickLesk](https://github.com/MickLesk) ([#16252](https://github.com/community-scripts/ProxmoxVE/pull/16252))
- #### 🔧 Refactor
- Refactor: harmonize tools/addon and move boilerplate into core.func [@MickLesk](https://github.com/MickLesk) ([#16202](https://github.com/community-scripts/ProxmoxVE/pull/16202))
## 2026-08-03
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Correction to link in Paperless-NGX update script [@jsspen](https://github.com/jsspen) ([#16241](https://github.com/community-scripts/ProxmoxVE/pull/16241))
- fix restore env in split pro [@johanngrobe](https://github.com/johanngrobe) ([#16228](https://github.com/community-scripts/ProxmoxVE/pull/16228))
### 💾 Core
- #### 🔧 Refactor
- core: read all interactive prompts from /dev/tty, drain leftover input on read failure (hotfix) [@MickLesk](https://github.com/MickLesk) ([#16235](https://github.com/community-scripts/ProxmoxVE/pull/16235))
## 2026-08-02
### 🆕 New Scripts
- Portainer as Addon [@MickLesk](https://github.com/MickLesk) ([#16200](https://github.com/community-scripts/ProxmoxVE/pull/16200))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- LibreNMS: Ensure ipmitool dependency is installed [@tremor021](https://github.com/tremor021) ([#16219](https://github.com/community-scripts/ProxmoxVE/pull/16219))
- Bitfocus Companion: add libatomic1 dependency [@tremor021](https://github.com/tremor021) ([#16212](https://github.com/community-scripts/ProxmoxVE/pull/16212))
- fix(dispatcharr): add recordings and dvr queues to celery worker [@eXistC](https://github.com/eXistC) ([#16204](https://github.com/community-scripts/ProxmoxVE/pull/16204))
- add retry for uv - same as immich [@asylumexp](https://github.com/asylumexp) ([#16203](https://github.com/community-scripts/ProxmoxVE/pull/16203))
- Fix for cross-seed node version regression [@TorinFrancis](https://github.com/TorinFrancis) ([#16209](https://github.com/community-scripts/ProxmoxVE/pull/16209))
- #### 🔧 Refactor
- chore: remove portainer setup from several scripts (moved to addon) [@MickLesk](https://github.com/MickLesk) ([#16201](https://github.com/community-scripts/ProxmoxVE/pull/16201))
## 2026-08-01
### 🚀 Updated Scripts
+18 -2
View File
@@ -314,12 +314,17 @@ jobs:
// ── Allow-lists (mirror the slash bot) ─────────────────────────────
const ALLOWED_FIELDS = {
name: 'string', description: 'string', logo: 'string', documentation: 'string',
website: 'string', project_url: 'string', github: 'string', config_path: 'string',
website: 'string', project_url: 'string', repository: 'string', config_path: 'string',
tags: 'string', port: 'number', default_user: 'nullable_string', default_passwd: 'nullable_string',
unprivileged: 'number', updateable: 'boolean', privileged: 'boolean', has_arm: 'boolean',
unprivileged: 'number', updateable: 'boolean', privileged: 'boolean',
architectures: 'select_list', platforms: 'select_list',
is_dev: 'boolean', is_disabled: 'boolean', disable_message: 'string',
is_deleted: 'boolean', deleted_message: 'string'
};
const SELECT_VALUES = {
architectures: ['amd64', 'arm64'],
platforms: ['pve', 'incus'],
};
const FIELD_TO_CT_VAR = { tags: 'var_tags', unprivileged: 'var_unprivileged' };
const RESOURCE_KEYS = { cpu: 'number', ram: 'number', hdd: 'number', os: 'string', version: 'string' };
const METHOD_KEYS = { config_path: 'string', script: 'string' };
@@ -339,6 +344,17 @@ jobs:
if (isNaN(n)) return { error: '`' + key + '` must be a number' };
return { value: n };
}
if (type === 'select_list') {
// architectures/platforms are multi-selects over a closed set,
// so an unknown value is rejected rather than stored. The model
// may hand back an array or a comma-separated string.
const allowed = SELECT_VALUES[key] || [];
const raw = Array.isArray(rawVal) ? rawVal : String(rawVal == null ? '' : rawVal).split(',');
const values = raw.map(function (v) { return String(v).trim(); }).filter(Boolean);
const bad = values.filter(function (v) { return allowed.indexOf(v) === -1; });
if (bad.length > 0) return { error: '`' + key + '` accepts ' + allowed.join(', ') + ' — got: ' + bad.join(', ') };
return { value: values };
}
if (type === 'nullable_string') return { value: rawVal === '' || rawVal == null ? null : String(rawVal) };
return { value: String(rawVal) };
}
+25 -6
View File
@@ -323,9 +323,10 @@ jobs:
'/pocketbase <slug> method remove <type>\n' +
'```\n' +
'Method fields: `cpu` `ram` `hdd` `os` `version` `config_path` `script`\n\n' +
'**Editable fields:** `name` `description` `logo` `documentation` `website` `project_url` `github` ' +
'**Editable fields:** `name` `description` `logo` `documentation` `website` `project_url` `repository` ' +
'`config_path` `port` `default_user` `default_passwd` ' +
'`updateable` `privileged` `has_arm` `is_dev` ' +
'`updateable` `privileged` `is_dev` ' +
'`architectures` (amd64,arm64) `platforms` (pve,incus) ' +
'`is_disabled` `disable_message` `is_deleted` `deleted_message`';
if (!withoutCmd) {
@@ -504,7 +505,8 @@ jobs:
out.push('- **Port:** ' + (record.port != null ? '`' + record.port + '`' : '—'));
out.push('- **Updateable:** ' + (record.updateable ? 'Yes' : 'No'));
out.push('- **Privileged:** ' + (record.privileged ? 'Yes' : 'No'));
out.push('- **ARM:** ' + (record.has_arm ? 'Yes' : 'No'));
out.push('- **Architectures:** ' + ((record.architectures || []).join(', ') || 'amd64'));
out.push('- **Platforms:** ' + ((record.platforms || []).join(', ') || 'pve'));
if (record.is_dev) out.push('- **Dev:** Yes');
if (record.is_disabled) out.push('- **Disabled:** Yes' + (record.disable_message ? ' — ' + record.disable_message : ''));
if (record.is_deleted) out.push('- **Deleted:** Yes' + (record.deleted_message ? ' — ' + record.deleted_message : ''));
@@ -838,7 +840,7 @@ jobs:
const fieldName = setMatch[1].toLowerCase();
const SET_ALLOWED = {
name: 'string', description: 'string', logo: 'string',
documentation: 'string', website: 'string', project_url: 'string', github: 'string',
documentation: 'string', website: 'string', project_url: 'string', repository: 'string',
config_path: 'string', disable_message: 'string', deleted_message: 'string'
};
if (!SET_ALLOWED[fieldName]) {
@@ -888,7 +890,7 @@ jobs:
documentation: 'string',
website: 'string',
project_url: 'string',
github: 'string',
repository: 'string',
config_path: 'string',
tags: 'string',
port: 'number',
@@ -897,7 +899,8 @@ jobs:
unprivileged: 'number',
updateable: 'boolean',
privileged: 'boolean',
has_arm: 'boolean',
architectures: 'select_list',
platforms: 'select_list',
is_dev: 'boolean',
is_disabled: 'boolean',
disable_message: 'string',
@@ -924,6 +927,10 @@ jobs:
}
// Cast values to correct types
const SELECT_VALUES = {
architectures: ['amd64', 'arm64'],
platforms: ['pve', 'incus'],
};
const payload = {};
for (const [key, rawVal] of Object.entries(parsedFields)) {
const type = ALLOWED_FIELDS[key];
@@ -943,6 +950,18 @@ jobs:
process.exit(0);
}
payload[key] = n;
} else if (type === 'select_list') {
// architectures/platforms are multi-selects over a closed set,
// so an unknown value is rejected rather than stored.
const allowed = SELECT_VALUES[key] || [];
const values = rawVal.split(',').map(function (v) { return v.trim(); }).filter(Boolean);
const bad = values.filter(function (v) { return allowed.indexOf(v) === -1; });
if (bad.length > 0) {
await addReaction('-1');
await postComment('❌ **PocketBase Bot**: `' + key + '` accepts ' + allowed.join(', ') + ' — got: `' + bad.join(', ') + '`');
process.exit(0);
}
payload[key] = values;
} else if (type === 'nullable_string') {
payload[key] = rawVal === '' ? null : rawVal;
} else {
+13 -1
View File
@@ -179,7 +179,19 @@ jobs:
if (resolvedType) payload.type = resolvedType;
var resolvedCats = (data.categories || []).map(function(n) { return categoryNameToPbId[categoryIdToName[n]]; }).filter(Boolean);
if (resolvedCats.length) payload.categories = resolvedCats;
if (data.has_arm !== undefined) payload.has_arm = data.has_arm === true || data.has_arm === 'true';
// architectures replaces has_arm: a boolean could say "also ARM" but
// not "ARM only" or "amd64 only". A record written before the field
// existed is read through the old key so nothing silently drops.
if (Array.isArray(data.architectures)) {
payload.architectures = data.architectures.filter(function (a) { return a === 'amd64' || a === 'arm64'; });
} else if (data.has_arm !== undefined) {
payload.architectures = (data.has_arm === true || data.has_arm === 'true') ? ['amd64', 'arm64'] : ['amd64'];
}
if (Array.isArray(data.platforms)) {
payload.platforms = data.platforms.filter(function (p) { return p === 'pve' || p === 'incus'; });
}
if (Array.isArray(data.app_vars)) payload.app_vars = data.app_vars;
if (data.repository !== undefined) payload.repository = data.repository;
if (data.version !== undefined) payload.version = data.version;
if (data.changelog !== undefined) payload.changelog = data.changelog;
if (data.screenshots !== undefined) payload.screenshots = data.screenshots;
+66 -92
View File
@@ -86,6 +86,9 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
@@ -99,7 +102,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
<details>
<summary><h4>August (1 entries)</h4></summary>
<summary><h4>August (8 entries)</h4></summary>
[View August 2026 Changelog](.github/changelogs/2026/08.md)
@@ -518,6 +521,67 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-08-10
### 🧰 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))
## 2026-08-06
### 🚀 Updated Scripts
@@ -1134,94 +1198,4 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- Adapt to new artifact filename format for pocket id [@wollew](https://github.com/wollew) ([#15689](https://github.com/community-scripts/ProxmoxVE/pull/15689))
- Fireshare: Fix for install and upgrade to v1.7.3 [@tremor021](https://github.com/tremor021) ([#15673](https://github.com/community-scripts/ProxmoxVE/pull/15673))
- Endurain: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15674](https://github.com/community-scripts/ProxmoxVE/pull/15674))
## 2026-07-09
### 🚀 Updated Scripts
- fix(pihole): repair Unbound DNS-over-TLS (DoT) forwarding config [@TowyTowy](https://github.com/TowyTowy) ([#15654](https://github.com/community-scripts/ProxmoxVE/pull/15654))
## 2026-07-08
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Opencloud: Bump version to 7.2.1 [@vhsdream](https://github.com/vhsdream) ([#15655](https://github.com/community-scripts/ProxmoxVE/pull/15655))
- BabyBuddy: Harden update script [@MickLesk](https://github.com/MickLesk) ([#15642](https://github.com/community-scripts/ProxmoxVE/pull/15642))
## 2026-07-07
### 🆕 New Scripts
- Forgejo-Runner ([#15046](https://github.com/community-scripts/ProxmoxVE/pull/15046))
## 2026-07-06
### 🚀 Updated Scripts
- Fix alignment in various ct end messages [@tremor021](https://github.com/tremor021) ([#15632](https://github.com/community-scripts/ProxmoxVE/pull/15632))
- Immich: Update libvips to 8.18.4 [@vhsdream](https://github.com/vhsdream) ([#15619](https://github.com/community-scripts/ProxmoxVE/pull/15619))
- #### 🐞 Bug Fixes
- Wizarr: Build JS and CSS static assets [@vhsdream](https://github.com/vhsdream) ([#15634](https://github.com/community-scripts/ProxmoxVE/pull/15634))
- RustDesk Server: Update URL format in rustdeskserver.sh [@tremor021](https://github.com/tremor021) ([#15626](https://github.com/community-scripts/ProxmoxVE/pull/15626))
- attempt to port docker-vm to support arm64 [@asylumexp](https://github.com/asylumexp) ([#15611](https://github.com/community-scripts/ProxmoxVE/pull/15611))
- fix(plane): don't clobber global app var, breaking /usr/bin/update [@asylumexp](https://github.com/asylumexp) ([#15612](https://github.com/community-scripts/ProxmoxVE/pull/15612))
- #### 🔧 Refactor
- cliproxyapi: point setup message at /management.html [@austinpilz](https://github.com/austinpilz) ([#15628](https://github.com/community-scripts/ProxmoxVE/pull/15628))
### 🗑️ Deleted Scripts
- Remove: FlowiseAI [@MickLesk](https://github.com/MickLesk) ([#15624](https://github.com/community-scripts/ProxmoxVE/pull/15624))
## 2026-07-05
### 🆕 New Scripts
- excalidash ([#15604](https://github.com/community-scripts/ProxmoxVE/pull/15604))
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- fix: homarr: cli [@CrazyWolf13](https://github.com/CrazyWolf13) ([#15603](https://github.com/community-scripts/ProxmoxVE/pull/15603))
- immich: vacuum smart_search/face_search before VectorChord bump [@irishpadres](https://github.com/irishpadres) ([#15607](https://github.com/community-scripts/ProxmoxVE/pull/15607))
## 2026-07-04
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Element Synapse: Fix heredoc syntax in elementsynapse-install.sh [@tremor021](https://github.com/tremor021) ([#15594](https://github.com/community-scripts/ProxmoxVE/pull/15594))
- Twenty: Fix backup restore [@tremor021](https://github.com/tremor021) ([#15586](https://github.com/community-scripts/ProxmoxVE/pull/15586))
- fix(endurain): update frontend dist path after upstream restructure [@joaovitoriasilva](https://github.com/joaovitoriasilva) ([#15590](https://github.com/community-scripts/ProxmoxVE/pull/15590))
## 2026-07-03
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Immich: handle mise monorepo_root rename correctly | bump to 3.0.1 [@MickLesk](https://github.com/MickLesk) ([#15557](https://github.com/community-scripts/ProxmoxVE/pull/15557))
- #### ✨ New Features
- Opencloud: bump to v7.2.0 [@vhsdream](https://github.com/vhsdream) ([#15575](https://github.com/community-scripts/ProxmoxVE/pull/15575))
### 💾 Core
- #### 🔧 Refactor
- tools.func: fix corepack/pnpm install flow in setup_nodejs [@MickLesk](https://github.com/MickLesk) ([#15579](https://github.com/community-scripts/ProxmoxVE/pull/15579))
### 🧰 Tools
- #### 🐞 Bug Fixes
- Removed deprecated parameter in Filebrowser Quantum configuration [@alpargatagazer](https://github.com/alpargatagazer) ([#15573](https://github.com/community-scripts/ProxmoxVE/pull/15573))
- Endurain: Fix update procedure [@tremor021](https://github.com/tremor021) ([#15674](https://github.com/community-scripts/ProxmoxVE/pull/15674))
+49
View File
@@ -103,6 +103,55 @@ Key rules at a glance:
- Quote all variables: `"$VAR"` not `$VAR`
- Use lowercase variable names
- Do not hardcode credentials or sensitive values
- Never prompt without an escape hatch — see below
### Answering a prompt up front
An install script that only asks cannot be deployed unattended. Read the
variable first and prompt only when it is unset:
```bash
if [[ -z "${var_admin_user:-}" ]]; then
read -r -p "${TAB3}Admin username: " var_admin_user
fi
var_admin_user="${var_admin_user:-admin}"
```
Name them `var_<something>`, the same namespace the container variables use.
`install/forgejo-runner-install.sh`, `install/pangolin-install.sh`, and `install/docker-install.sh` all
follow this.
The variable also has to be exported from `ct/<app>.sh`, or it never reaches
the container — `lxc-attach` carries the caller's environment, but only for
what was actually exported:
```bash
export var_admin_user="${var_admin_user:-}"
```
Declare them on the script's PocketBase record in `app_vars` so the website's
generator can offer them as fields:
```json
"app_vars": [
{
"name": "var_admin_user",
"label": "Admin Username",
"type": "text",
"default": "admin"
},
{
"name": "var_admin_pass",
"label": "Admin Password",
"type": "password",
"secret": true
}
]
```
`type` is one of `text`, `password`, `number`, `boolean` (`yes`/`no`) or
`select` (with `options`). Mark anything credential-like `secret` — the
generator keeps those out of shareable links and out of the on-screen summary.
Full standards and examples: **[community-scripts.org/docs/contribution](https://community-scripts.org/docs/contribution)**
+14 -4
View File
@@ -171,11 +171,21 @@ This project runs on community contributions. Whether you want to write new scri
</p>
<p align="center">
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
<a href="https://www.star-history.com/?repos=community-scripts%2FProxmoxVE&type=date&legend=top-left">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" width="700" />
<source
media="(prefers-color-scheme: dark)"
srcset="https://api.star-history.com/chart?repos=community-scripts/ProxmoxVE&type=date&theme=dark&legend=top-left&sealed_token=-lUy2KH6pJryUyLCbiWRwFz3ilXMDFVFHm0lJcqh-Hl5e0QNNKjINNcXzULhaZVpBugN_TDaxOawEAuzwBc5Sjqa2mCRw9K6TdCioKRDsS_qXUwhkLQSCMRSg1schCdl4rQD8qEj7PWBjin-fyHnDm7NnM6akZp59jndG7qV7PrvG8nLBgDIuuA-wAI3"
/>
<source
media="(prefers-color-scheme: light)"
srcset="https://api.star-history.com/chart?repos=community-scripts/ProxmoxVE&type=date&legend=top-left&sealed_token=-lUy2KH6pJryUyLCbiWRwFz3ilXMDFVFHm0lJcqh-Hl5e0QNNKjINNcXzULhaZVpBugN_TDaxOawEAuzwBc5Sjqa2mCRw9K6TdCioKRDsS_qXUwhkLQSCMRSg1schCdl4rQD8qEj7PWBjin-fyHnDm7NnM6akZp59jndG7qV7PrvG8nLBgDIuuA-wAI3"
/>
<img
alt="Star History Chart"
src="https://api.star-history.com/chart?repos=community-scripts/ProxmoxVE&type=date&legend=top-left&sealed_token=-lUy2KH6pJryUyLCbiWRwFz3ilXMDFVFHm0lJcqh-Hl5e0QNNKjINNcXzULhaZVpBugN_TDaxOawEAuzwBc5Sjqa2mCRw9K6TdCioKRDsS_qXUwhkLQSCMRSg1schCdl4rQD8qEj7PWBjin-fyHnDm7NnM6akZp59jndG7qV7PrvG8nLBgDIuuA-wAI3"
width="700"
/>
</picture>
</a>
</p>
+1 -1
View File
@@ -81,7 +81,7 @@ function update_script() {
msg_info "Configuring Byparr"
cd /opt/Byparr
$STD uv sync --link-mode copy
$STD uv run camoufox fetch
$STD uv run python -m invisible_playwright fetch
msg_ok "Configured Byparr"
msg_info "Starting Service"
+1 -1
View File
@@ -44,6 +44,7 @@ function update_script() {
CLEAN_INSTALL=1 fetch_and_deploy_gl_release "Crafty-Controller" "crafty-controller/crafty-4" "tarball" "latest" "/opt/crafty-controller/crafty/crafty-4"
chown -R crafty:crafty /opt/crafty-controller
restore_backup
msg_info "Updating TemurinJDK"
@@ -53,7 +54,6 @@ function update_script() {
msg_ok "Updated TemurinJDK"
msg_info "Updating Python dependencies"
chown -R crafty:crafty /opt/crafty-controller
cd /opt/crafty-controller/crafty/crafty-4
$STD sudo -u crafty bash -c '
source /opt/crafty-controller/crafty/.venv/bin/activate
-14
View File
@@ -42,20 +42,6 @@ function update_script() {
echo -e "${TAB}${TAB}${GN}bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)\"${CL}"
fi
if docker ps -a --format '{{.Names}}' | grep -q '^portainer_agent$'; then
msg_info "Updating Portainer Agent"
$STD docker pull portainer/agent:latest
$STD docker stop portainer_agent
$STD docker rm portainer_agent
$STD docker run -d \
-p 9001:9001 \
--name=portainer_agent \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes \
portainer/agent
msg_ok "Updated Portainer Agent"
fi
msg_ok "Updated successfully!"
exit
}
+5
View File
@@ -18,6 +18,7 @@ var_nesting="${var_nesting:-1}"
var_keyctl="${var_keyctl:-1}"
export var_forgejo_instance="${var_forgejo_instance:-}"
export var_forgejo_runner_uuid="${var_forgejo_runner_uuid:-}"
export var_forgejo_runner_token="${var_forgejo_runner_token:-}"
export var_runner_labels="${var_runner_labels:-}"
@@ -64,6 +65,10 @@ if [[ -n "${mode:-}" ]]; then
msg_error "var_forgejo_instance is required for unattended installs."
exit 1
fi
if [[ -z "${var_forgejo_runner_uuid:-}" ]]; then
msg_error "var_forgejo_runner_uuid is required for unattended installs."
exit 1
fi
if [[ -z "${var_forgejo_runner_token:-}" ]]; then
msg_error "var_forgejo_runner_token is required for unattended installs."
exit 1
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://about.gitlab.com/
APP="GitLab"
var_tags="${var_tags:-git;devtools}"
var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-8192}"
var_disk="${var_disk:-40}"
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 [[ ! -d /opt/gitlab ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating GitLab (Patience)"
$STD apt update
$STD apt install -y gitlab-ce
msg_ok "Updated GitLab"
msg_info "Reconfiguring GitLab (Patience)"
$STD gitlab-ctl reconfigure
msg_ok "Reconfigured GitLab"
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}${CL}"
echo -e "${INFO}${YW}The initial root password is valid for 24 hours:${CL}"
echo -e "${TAB}${DEFAULT}${BGN}cat /etc/gitlab/initial_root_password${CL}"
+6
View File
@@ -0,0 +1,6 @@
_______ __ __ __
/ ____(_) /_/ / ____ _/ /_
/ / __/ / __/ / / __ `/ __ \
/ /_/ / / /_/ /___/ /_/ / /_/ /
\____/_/\__/_____/\__,_/_.___/
+6
View File
@@ -0,0 +1,6 @@
____ _
/ _/___ _____ (_)____
/ // __ `/ __ \/ / ___/
_/ // /_/ / / / / (__ )
/___/\__, /_/ /_/_/____/
/____/
+6
View File
@@ -0,0 +1,6 @@
_ __ __ __ ____ __ _ _
/ | / /__ / /__ ______ _____/ /__/ __ \____ / /_(_)___ ___ (_)___ ___ _____
/ |/ / _ \/ __/ | /| / / __ \/ ___/ //_/ / / / __ \/ __/ / __ `__ \/ /_ / / _ \/ ___/
/ /| / __/ /_ | |/ |/ / /_/ / / / ,< / /_/ / /_/ / /_/ / / / / / / / / /_/ __/ /
/_/ |_/\___/\__/ |__/|__/\____/_/ /_/|_|\____/ .___/\__/_/_/ /_/ /_/_/ /___/\___/_/
/_/
+6
View File
@@ -0,0 +1,6 @@
____ __
/ __ \_____/ /_
/ / / / ___/ __ \
/ /_/ / / / /_/ /
\____/_/ /_.___/
+36 -9
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# Author: MickLesk (CanbiZ) | Co-Author: Tom Frenzel (tomfrenzel)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/danielbrendel/hortusfox-web
@@ -34,29 +34,56 @@ function update_script() {
systemctl stop apache2
msg_ok "Stopped Service"
msg_info "Backing up current HortusFox installation"
cd /opt
mv /opt/hortusfox/ /opt/hortusfox-backup
msg_ok "Backed up current HortusFox installation"
cd /opt/hortusfox
if [[ ! -s app/migrations/migrations.list ]]; then
msg_info "Rebuilding HortusFox migration history"
local database_tables
database_tables="$(mariadb -u root -D hortusfox -NBe "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE();")"
: >app/migrations/migrations.list
local migration migration_file table_name
for migration in app/migrations/*.php; do
migration_file="${migration##*/}"
table_name="${migration_file%.php}"
if [[ "$migration_file" == "VersionModel.php" ]] || grep -Fxq "$table_name" <<<"$database_tables"; then
php -r 'echo hash("sha512", $argv[1]), PHP_EOL;' -- "$migration_file" >>app/migrations/migrations.list
fi
done
msg_ok "Rebuilt HortusFox migration history"
fi
if [[ ! -f app/migrations/verhist.json && -f ~/.hortusfox ]]; then
printf '["%s"]\n' "$(<~/.hortusfox)" >app/migrations/verhist.json
fi
create_backup \
/opt/hortusfox/.env \
/opt/hortusfox/app/migrations/migrations.list \
/opt/hortusfox/app/migrations/verhist.json \
/opt/hortusfox/public/img \
/opt/hortusfox/public/attachments \
/opt/hortusfox/public/backup \
/opt/hortusfox/public/exports \
/opt/hortusfox/public/snd \
/opt/hortusfox/public/themes
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "hortusfox" "danielbrendel/hortusfox-web" "tarball"
restore_backup
msg_info "Updating HortusFox"
cd /opt/hortusfox
cp /opt/hortusfox-backup/.env /opt/hortusfox/.env
cp -a /opt/hortusfox-backup/public/img/. /opt/hortusfox/public/img/
export COMPOSER_ALLOW_SUPERUSER=1
$STD composer install --no-dev --optimize-autoloader
$STD php asatru migrate:list
$STD php asatru migrate:upgrade
$STD php asatru plants:attributes
$STD php asatru calendar:classes
$STD php asatru plants:attributes
$STD php asatru aquashell:config
chown -R www-data:www-data /opt/hortusfox
rm -r /opt/hortusfox-backup
msg_ok "Updated HortusFox"
msg_info "Starting Service"
systemctl start apache2
msg_ok "Started Service"
msg_ok "Updated successfully!"
fi
exit
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Nystik-gh/ignis
APP="Ignis"
var_tags="${var_tags:-notes;obsidian}"
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_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/ignis ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "ignis" "Nystik-gh/ignis"; then
msg_info "Stopping Service"
systemctl stop ignis
msg_ok "Stopped Service"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "ignis" "Nystik-gh/ignis" "tarball"
msg_info "Building Ignis"
cd /opt/ignis
export NODE_OPTIONS="--max-old-space-size=4096"
export IGNIS_BUILD="$(cat ~/.ignis)"
$STD npm ci --ignore-scripts
$STD npm run build
$STD npm install -g @electron/asar
msg_ok "Built Ignis"
msg_info "Checking Obsidian Web Assets"
OBSIDIAN_VERSION=$(grep -oP 'OBSIDIAN_VERSION=\K[0-9.]+' /opt/ignis/apps/ignis-server/Dockerfile | head -n1)
[[ -z "$OBSIDIAN_VERSION" ]] && OBSIDIAN_VERSION="$(cat /opt/ignis_data/obsidian.version 2>/dev/null)"
if [[ -n "$OBSIDIAN_VERSION" && "$OBSIDIAN_VERSION" != "$(cat /opt/ignis_data/obsidian.version 2>/dev/null)" ]]; then
rm -rf /opt/ignis_data/obsidian-app
mkdir -p /opt/ignis_data/obsidian-app
curl -fsSL -o /tmp/obsidian.asar.gz "https://github.com/obsidianmd/obsidian-releases/releases/download/v${OBSIDIAN_VERSION}/obsidian-${OBSIDIAN_VERSION}.asar.gz"
gunzip -f /tmp/obsidian.asar.gz
$STD asar extract /tmp/obsidian.asar /opt/ignis_data/obsidian-app
rm -f /tmp/obsidian.asar
echo "${OBSIDIAN_VERSION}" >/opt/ignis_data/obsidian.version
fi
msg_ok "Checked Obsidian Web Assets"
msg_info "Starting Service"
systemctl start ignis
systemctl reload nginx
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}https://${IP}${CL}"
+10 -1
View File
@@ -214,7 +214,16 @@ EOF
cd "$SRC_DIR"
export MISE_TRUSTED_CONFIG_PATHS="$SRC_DIR"/mise.toml
export MISE_DISABLE_TOOLS=github:jellyfin/jellyfin-ffmpeg
$STD mise install
mise_ok=0
for i in 1 2 3; do
$STD mise install && {
mise_ok=1
break
}
msg_warn "mise install failed (attempt $i/3) - retrying"
sleep 5
done
[[ "$mise_ok" -eq 1 ]] || exit 1
export PATH="$(mise bin-paths 2>/dev/null | tr '\n' ':')$PATH"
if ! command -v extism-js >/dev/null 2>&1; then
# extism-js ships as a bare gzip-compressed single binary (.gz) that
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/Ozark-Connect/NetworkOptimizer
APP="NetworkOptimizer"
var_tags="${var_tags:-network;monitoring;unifi}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-12}"
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 [[ ! -d /opt/networkoptimizer ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
if check_for_gh_release "networkoptimizer" "Ozark-Connect/NetworkOptimizer"; then
msg_info "Stopping Service"
systemctl stop networkoptimizer
msg_ok "Stopped Service"
create_backup /opt/networkoptimizer/networkoptimizer.env
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "networkoptimizer" "Ozark-Connect/NetworkOptimizer" "tarball"
msg_info "Rebuilding NetworkOptimizer"
RID="linux-x64"
[[ "$(dpkg --print-architecture)" == "arm64" ]] && RID="linux-arm64"
cd /opt/networkoptimizer
$STD dotnet publish src/NetworkOptimizer.Web -c Release -r "$RID" --self-contained -o /opt/networkoptimizer/publish
chmod +x /opt/networkoptimizer/publish/NetworkOptimizer.Web
mkdir -p /opt/networkoptimizer/publish/tools
cd /opt/networkoptimizer/src/uwnspeedtest
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $STD go build -trimpath -ldflags "-s -w" -o /opt/networkoptimizer/publish/tools/uwnspeedtest-linux-arm64 .
msg_ok "Rebuilt NetworkOptimizer"
restore_backup
msg_info "Starting Service"
systemctl start networkoptimizer
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}:8042${CL}"
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
# Copyright (c) 2021-2026 community-scripts ORG
# Author: angusmaul
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://orb.net/
APP="Orb"
var_tags="${var_tags:-network;monitoring}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-512}"
var_disk="${var_disk:-4}"
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 ! dpkg -s orb >/dev/null 2>&1; then
msg_error "No ${APP} Installation Found!"
exit 233
fi
msg_info "Updating Orb"
$STD apt update
$STD apt install -y --only-upgrade orb
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 "${TAB}${GATEWAY}${BGN}To link the sensor to your orb account run:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}pct exec ${CTID} -- runuser -u orb -- orb link${CL}"
+3
View File
@@ -17,6 +17,9 @@ var_arm64="${var_arm64:-yes}"
var_unprivileged="${var_unprivileged:-1}"
var_tun="${var_tun:-1}"
export var_pangolin_url="${var_pangolin_url:-}"
export var_pangolin_email="${var_pangolin_email:-}"
header_info "$APP"
variables
color
+1
View File
@@ -30,6 +30,7 @@ function update_script() {
exit
fi
ensure_dependencies git
if check_for_gh_release "sparkyfitness" "CodeWithCJ/SparkyFitness"; then
msg_info "Stopping Services"
systemctl stop sparkyfitness-server nginx
+1 -1
View File
@@ -14,7 +14,7 @@ network_check
update_os
msg_info "Installing Apache CouchDB"
ERLANG_COOKIE=$(openssl rand -base64 32)
ERLANG_COOKIE=$(openssl rand -hex 32)
ADMIN_PASS="$(openssl rand -base64 18 | cut -c1-13)"
debconf-set-selections <<<"couchdb couchdb/cookie string $ERLANG_COOKIE"
debconf-set-selections <<<"couchdb couchdb/mode select standalone"
+1 -1
View File
@@ -58,7 +58,7 @@ fetch_and_deploy_gh_release "Byparr" "ThePhaseless/Byparr" "tarball" "latest"
msg_info "Configuring Byparr"
cd /opt/Byparr
$STD uv sync --link-mode copy
$STD uv run camoufox fetch
$STD uv run python -m invisible_playwright fetch
msg_ok "Configured Byparr"
msg_info "Creating Service"
-1
View File
@@ -83,7 +83,6 @@ $STD apt-get install -y \
fonts-kacst fonts-liberation \
fonts-noto-cjk \
fonts-noto-color-emoji \
msttcorefonts \
fonts-roboto \
fonts-thai-tlwg \
fonts-wqy-zenhei
+51
View File
@@ -0,0 +1,51 @@
#!/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://about.gitlab.com/
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 \
openssh-server \
perl \
tzdata
msg_ok "Installed Dependencies"
setup_deb822_repo \
"gitlab-ce" \
"https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey" \
"https://packages.gitlab.com/gitlab/gitlab-ce/debian" \
"$(get_os_info codename)" \
"main"
msg_info "Configuring GitLab"
mkdir -p /etc/gitlab
cat <<EOF >/etc/gitlab/gitlab.rb
external_url 'http://${LOCAL_IP}'
# Omnibus runs 'sysctl -e --system' during reconfigure, which fails in an
# unprivileged LXC because most kernel keys are not writable.
package['modify_kernel_parameters'] = false
EOF
msg_ok "Configured GitLab"
msg_info "Installing GitLab CE (Patience)"
$STD apt install -y gitlab-ce
msg_ok "Installed GitLab CE"
msg_info "Reconfiguring GitLab (Patience)"
$STD gitlab-ctl reconfigure
msg_ok "Reconfigured GitLab"
motd_ssh
customize
cleanup_lxc
+5 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: MickLesk (CanbiZ)
# Author: MickLesk (CanbiZ) | Co-Author: Tom Frenzel (tomfrenzel)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/danielbrendel/hortusfox-web
@@ -36,12 +36,15 @@ msg_ok "Composer dependencies installed"
msg_info "Running DB migration"
$STD php asatru migrate:fresh
HORTUSFOX_VERSION="$(<~/.hortusfox)"
printf '["%s"]\n' "$HORTUSFOX_VERSION" >/opt/hortusfox/app/migrations/verhist.json
msg_ok "Migration finished"
msg_info "Setting up HortusFox"
$STD mariadb -u root -D $MARIADB_DB_NAME -e "INSERT IGNORE INTO AppModel (workspace, language, created_at) VALUES ('Default Workspace', 'en', NOW());"
$STD php asatru plants:attributes
$STD php asatru calendar:classes
$STD php asatru plants:attributes
$STD php asatru aquashell:config
ADMIN_EMAIL="admin@example.com"
ADMIN_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)"
ADMIN_HASH=$(php -r "echo password_hash('$ADMIN_PASS', PASSWORD_BCRYPT);")
+113
View File
@@ -0,0 +1,113 @@
#!/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/Nystik-gh/ignis
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 nginx
msg_ok "Installed Dependencies"
NODE_VERSION="22" setup_nodejs
fetch_and_deploy_gh_release "ignis" "Nystik-gh/ignis" "tarball"
msg_info "Building Ignis"
cd /opt/ignis
export NODE_OPTIONS="--max-old-space-size=4096"
export IGNIS_BUILD="$(cat ~/.ignis)"
$STD npm ci --ignore-scripts
$STD npm run build
$STD npm install -g @electron/asar
msg_ok "Built Ignis"
msg_info "Downloading Obsidian Web Assets"
mkdir -p /opt/ignis_data/{obsidian-app,vaults,data}
OBSIDIAN_VERSION=$(grep -oP 'OBSIDIAN_VERSION=\K[0-9.]+' /opt/ignis/apps/ignis-server/Dockerfile | head -n1)
[[ -z "$OBSIDIAN_VERSION" ]] && OBSIDIAN_VERSION="1.12.7"
curl -fsSL -o /tmp/obsidian.asar.gz "https://github.com/obsidianmd/obsidian-releases/releases/download/v${OBSIDIAN_VERSION}/obsidian-${OBSIDIAN_VERSION}.asar.gz"
gunzip -f /tmp/obsidian.asar.gz
$STD asar extract /tmp/obsidian.asar /opt/ignis_data/obsidian-app
rm -f /tmp/obsidian.asar
echo "${OBSIDIAN_VERSION}" >/opt/ignis_data/obsidian.version
msg_ok "Downloaded Obsidian Web Assets"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/ignis.service
[Unit]
Description=Ignis (Obsidian in the browser)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/ignis
Environment=NODE_ENV=production
Environment=PORT=8080
Environment=VAULT_ROOT=/opt/ignis_data/vaults
Environment=DATA_ROOT=/opt/ignis_data/data
Environment=OBSIDIAN_ASSETS_PATH=/opt/ignis_data/obsidian-app
Environment=AUTO_CREATE_DEFAULT=true
ExecStart=/usr/bin/node /opt/ignis/apps/ignis-server/server/index.js
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now ignis
msg_ok "Created Service"
msg_info "Generating Self-Signed Certificate"
create_self_signed_cert "ignis"
msg_ok "Generated Self-Signed Certificate"
msg_info "Configuring Nginx"
cat <<'EOF' >/etc/nginx/sites-available/ignis.conf
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
http2 on;
server_name _;
ssl_certificate /etc/ssl/ignis/ignis.crt;
ssl_certificate_key /etc/ssl/ignis/ignis.key;
client_max_body_size 1024m;
location / {
proxy_pass http://127.0.0.1:8080;
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;
proxy_read_timeout 3600s;
}
}
EOF
ln -sf /etc/nginx/sites-available/ignis.conf /etc/nginx/sites-enabled/ignis.conf
rm -f /etc/nginx/sites-enabled/default
systemctl restart nginx
msg_ok "Configured Nginx"
motd_ssh
customize
cleanup_lxc
+10 -1
View File
@@ -355,7 +355,16 @@ cp LICENSE "$APP_DIR"
cd "$SRC_DIR"
export MISE_TRUSTED_CONFIG_PATHS="$SRC_DIR"/mise.toml
export MISE_DISABLE_TOOLS=github:jellyfin/jellyfin-ffmpeg
$STD mise install
mise_ok=0
for i in 1 2 3; do
$STD mise install && {
mise_ok=1
break
}
msg_warn "mise install failed (attempt $i/3) - retrying"
sleep 5
done
[[ "$mise_ok" -eq 1 ]] || exit 1
export PATH="$(mise bin-paths 2>/dev/null | tr '\n' ':')$PATH"
if ! command -v extism-js >/dev/null 2>&1; then
# extism-js is published as a bare gzip-compressed single binary (.gz), which
+79
View File
@@ -0,0 +1,79 @@
#!/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/Ozark-Connect/NetworkOptimizer
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 \
git \
sshpass \
iperf3
setup_deb822_repo \
"microsoft" \
"https://packages.microsoft.com/keys/microsoft-2025.asc" \
"https://packages.microsoft.com/debian/13/prod/" \
"trixie"
$STD apt install -y dotnet-sdk-10.0
msg_ok "Installed Dependencies"
setup_go
fetch_and_deploy_gh_release "networkoptimizer" "Ozark-Connect/NetworkOptimizer" "tarball"
msg_info "Building NetworkOptimizer"
RID="linux-x64"
[[ "$(dpkg --print-architecture)" == "arm64" ]] && RID="linux-arm64"
cd /opt/networkoptimizer
export MinVerVersionOverride="$(cat ~/.networkoptimizer)"
$STD dotnet publish src/NetworkOptimizer.Web -c Release -r "$RID" --self-contained -o /opt/networkoptimizer/publish
chmod +x /opt/networkoptimizer/publish/NetworkOptimizer.Web
msg_ok "Built NetworkOptimizer"
msg_info "Building Gateway Speed Test Binary"
mkdir -p /opt/networkoptimizer/publish/tools
cd /opt/networkoptimizer/src/uwnspeedtest
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $STD go build -trimpath -ldflags "-s -w" -o /opt/networkoptimizer/publish/tools/uwnspeedtest-linux-arm64 .
msg_ok "Built Gateway Speed Test Binary"
msg_info "Configuring NetworkOptimizer"
cat <<EOF >/opt/networkoptimizer/networkoptimizer.env
ASPNETCORE_URLS=http://*:8042
HOST_IP=${LOCAL_IP}
Iperf3Server__Enabled=true
EOF
msg_ok "Configured NetworkOptimizer"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/networkoptimizer.service
[Unit]
Description=NetworkOptimizer
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/networkoptimizer/publish
EnvironmentFile=/opt/networkoptimizer/networkoptimizer.env
ExecStart=/opt/networkoptimizer/publish/NetworkOptimizer.Web
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now networkoptimizer
msg_ok "Created Service"
motd_ssh
customize
cleanup_lxc
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2026 community-scripts ORG
# Author: angusmaul
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://orb.net/
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
setup_deb822_repo \
"orb" \
"https://pkgs.orb.net/stable/debian/orbforge.noarmor.gpg" \
"https://pkgs.orb.net/stable/debian" \
"orb" \
"main"
msg_info "Installing Orb"
$STD apt install -y orb
msg_ok "Installed Orb"
msg_info "Enabling Service"
systemctl enable -q --now orb
msg_ok "Enabled Service"
motd_ssh
customize
cleanup_lxc
+11 -2
View File
@@ -27,9 +27,18 @@ fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VER
fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_$(arch_resolve)"
fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_$(arch_resolve).tar.gz"
read -rp "${TAB3}Enter your Pangolin URL (ex: https://pangolin.example.com): " pango_url
# Read the variable first and prompt only when it is unset, so the install can
# be supplied up front. Same convention as install/forgejo-runner-install.sh.
pango_url="${var_pangolin_url:-}"
if [[ -z "$pango_url" ]]; then
read -rp "${TAB3}Enter your Pangolin URL (ex: https://pangolin.example.com): " pango_url
fi
[[ "$pango_url" != https://* && "$pango_url" != http://* ]] && pango_url="https://${pango_url}"
read -rp "${TAB3}Enter your email address: " pango_email
pango_email="${var_pangolin_email:-}"
if [[ -z "$pango_email" ]]; then
read -rp "${TAB3}Enter your email address: " pango_email
fi
msg_info "Setup Pangolin"
SECRET_KEY=$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32)
+3
View File
@@ -103,6 +103,9 @@ cat <<EOF >/etc/clickhouse-server/config.d/cluster.xml
<shard>01</shard>
<replica>01</replica>
</macros>
<merge_tree>
<allow_dimensions_outside_sorting_key>1</allow_dimensions_outside_sorting_key>
</merge_tree>
</clickhouse>
EOF
systemctl enable -q --now clickhouse-server
+1 -1
View File
@@ -14,7 +14,7 @@ network_check
update_os
msg_info "Installing Dependencies"
$STD apt install -y nginx
$STD apt install -y git nginx
msg_ok "Installed Dependencies"
PG_VERSION="18" setup_postgresql
+1 -1
View File
@@ -66,7 +66,7 @@ for i in {1..15}; do
fi
sleep 2
done
$STD mariadb -u webtrees -p"${MARIADB_DB_PASS}" -h 127.0.0.1 webtrees -e "SHOW TABLES LIKE 'wt_user';" | grep -q wt_user
mariadb -u webtrees -p"${MARIADB_DB_PASS}" -h 127.0.0.1 webtrees -e "SHOW TABLES LIKE 'wt_user';" | grep -q wt_user
msg_ok "Initialized Webtrees database schema"
$STD sudo -u www-data php /opt/webtrees/index.php user Admin \
--create \
+2 -2
View File
@@ -925,7 +925,7 @@ _list_os_versions() {
local arch
arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)"
pveam available -section system 2>/dev/null |
grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)$" |
grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)([[:space:]]|$)" |
awk '{print $2}' |
sed -nE "s/^${ostype}-([0-9]+(\.[0-9]+)?).*/\1/p" |
sort -u -V || true
@@ -941,7 +941,7 @@ _list_templates() {
local arch
arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)"
pveam available -section system 2>/dev/null |
grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)$" |
grep -E "_${arch}\.(tar\.zst|tar\.xz|tar\.gz)([[:space:]]|$)" |
awk '{print $2}' |
grep -E "^${search}.*${pattern}" |
sort -t - -k 2 -V || true
+38 -60
View File
@@ -2576,11 +2576,6 @@ _deploy_unpacked_archive() {
local archive="$1" target="$2" workdir="$3"
local filename="${archive##*/}"
mkdir -p "$target"
if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
find "${target:?}" -mindepth 1 -delete
fi
if [[ "$filename" == *.zip ]]; then
ensure_dependencies unzip
unzip -q "$archive" -d "$workdir" || {
@@ -2607,38 +2602,44 @@ _deploy_unpacked_archive() {
return 65
fi
local top_entries inner_dir
local top_entries inner_dir source_dir
top_entries=$(find "$workdir" -mindepth 1 -maxdepth 1)
if [[ "$(echo "$top_entries" | wc -l)" -eq 1 && -d "$top_entries" ]]; then
inner_dir="$top_entries"
shopt -s dotglob nullglob
if compgen -G "$inner_dir/*" >/dev/null; then
cp -r "$inner_dir"/* "$target/" || {
msg_error "Failed to copy contents from $inner_dir to $target"
shopt -u dotglob nullglob
return 252
}
else
msg_error "Inner directory is empty: $inner_dir"
shopt -u dotglob nullglob
return 252
fi
shopt -u dotglob nullglob
source_dir="$inner_dir"
else
shopt -s dotglob nullglob
if compgen -G "$workdir/*" >/dev/null; then
cp -r "$workdir"/* "$target/" || {
msg_error "Failed to copy contents to $target"
shopt -u dotglob nullglob
return 252
}
source_dir="$workdir"
fi
shopt -s dotglob nullglob
if ! compgen -G "$source_dir/*" >/dev/null; then
if [[ -n "$inner_dir" ]]; then
msg_error "Inner directory is empty: $inner_dir"
else
msg_error "Unpacked archive is empty"
shopt -u dotglob nullglob
return 252
fi
shopt -u dotglob nullglob
return 252
fi
# <target> is only touched once the payload is known good. Wiping earlier left
# CLEAN_INSTALL callers with an empty target directory whenever the download
# was truncated, the archive was unreadable, or it unpacked to nothing.
mkdir -p "$target"
if [[ "${CLEAN_INSTALL:-0}" == "1" ]]; then
find "${target:?}" -mindepth 1 -delete
fi
if ! cp -r "$source_dir"/* "$target/"; then
if [[ -n "$inner_dir" ]]; then
msg_error "Failed to copy contents from $inner_dir to $target"
else
msg_error "Failed to copy contents to $target"
fi
shopt -u dotglob nullglob
return 252
fi
shopt -u dotglob nullglob
return 0
}
@@ -4801,8 +4802,8 @@ EOF
# Container Update Check
# - Skipped entirely when running unattended / non-interactive
# - Compose-managed containers: offered via Y/N → docker compose pull + up -d
# - Standalone containers: offered via Y/N → image pull only (no stop/rm)
# - Lists containers with a newer image available and the command to update
# them; does not pull/recreate anything itself
if [ "$docker_installed" = true ] && ! _docker_is_noninteractive; then
msg_info "Checking for container updates"
@@ -4840,41 +4841,14 @@ EOF
if [[ ${#compose_updates[@]} -eq 0 && ${#standalone_updates[@]} -eq 0 ]]; then
msg_ok "All containers are up-to-date"
else
local reply
msg_warn "Updates available (not applied automatically):"
for entry in "${compose_updates[@]}"; do
IFS='|' read -r name image compose_workdir compose_service <<<"$entry"
reply=""
if read -r -t 60 -p "${TAB3}Update ${name} (${image}) via Compose? <y/N> (auto-no in 60s): " reply </dev/tty; then
echo ""
else
echo ""
fi
if [[ "${reply,,}" =~ ^(y|yes)$ ]]; then
msg_info "Updating $name"
if (cd "$compose_workdir" && $STD docker compose pull "$compose_service" && $STD docker compose up -d "$compose_service"); then
msg_ok "Updated $name"
else
msg_warn "Could not update $name — try manually in $compose_workdir"
fi
fi
echo -e "${TAB3}${name} (${image}) — update via: cd ${compose_workdir} && docker compose pull ${compose_service} && docker compose up -d ${compose_service}"
done
for entry in "${standalone_updates[@]}"; do
IFS='|' read -r name image <<<"$entry"
reply=""
if read -r -t 60 -p "${TAB3}Pull new image for ${name} (${image})? <y/N> (auto-no in 60s): " reply </dev/tty; then
echo ""
else
echo ""
fi
if [[ "${reply,,}" =~ ^(y|yes)$ ]]; then
msg_info "Pulling new image for $name"
if $STD docker pull "$image"; then
msg_ok "New image available for $name — recreate the container to apply the update"
else
msg_warn "Failed to pull image for $name"
fi
fi
echo -e "${TAB3}${name} (${image}) — update via: docker pull ${image} && docker restart ${name}"
done
fi
fi
@@ -7732,6 +7706,10 @@ setup_nodejs() {
fi
fi
if [[ "$(npm -v 2>/dev/null | cut -d. -f1)" -ge 11 ]]; then
$STD npm config set dangerously-allow-all-scripts true --location=global 2>/dev/null || true
fi
# Set a safe default heap limit for Node.js builds if not explicitly provided.
# Priority:
# 1) NODE_OPTIONS (caller/user override)
+196 -36
View File
@@ -27,6 +27,10 @@ APP_TYPE="addon"
INSTALL_PATH="/opt/portainer"
COMPOSE_FILE="${INSTALL_PATH}/compose.yaml"
DEFAULT_PORT=9443
PORTAINER_IMAGE=""
COMPOSE_WORKDIR=""
COMPOSE_SERVICE=""
COMPOSE_CONFIG_FILES=""
# Initialize all core functions (colors, formatting, icons, STD mode)
load_functions
@@ -50,17 +54,184 @@ function uninstall() {
}
# ==============================================================================
# UPDATE
# UPDATE SCRIPT HELPER
# ==============================================================================
function update() {
function ensure_update_script() {
[[ -f /usr/local/bin/update_portainer ]] && return 0
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_portainer
#!/usr/bin/env bash
# Portainer Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_portainer
msg_ok "Created update script (/usr/local/bin/update_portainer)"
}
# ==============================================================================
# DETECT EXISTING INSTALLATION
# ==============================================================================
function detect_portainer() {
PORTAINER_IMAGE=""
COMPOSE_WORKDIR=""
COMPOSE_SERVICE=""
COMPOSE_CONFIG_FILES=""
if ! docker container inspect portainer &>/dev/null; then
return 0
fi
PORTAINER_IMAGE=$(docker inspect portainer --format '{{.Config.Image}}')
if [[ ! "$PORTAINER_IMAGE" =~ (^|/)portainer-(ce|ee)(:|@) ]]; then
msg_error "A container named 'portainer' exists but does not use an official Portainer CE or BE image."
exit 10
fi
COMPOSE_WORKDIR=$(docker inspect portainer --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' 2>/dev/null || true)
COMPOSE_SERVICE=$(docker inspect portainer --format '{{index .Config.Labels "com.docker.compose.service"}}' 2>/dev/null || true)
COMPOSE_CONFIG_FILES=$(docker inspect portainer --format '{{index .Config.Labels "com.docker.compose.project.config_files"}}' 2>/dev/null || true)
if [[ "$COMPOSE_WORKDIR" == "<no value>" ]]; then
COMPOSE_WORKDIR=""
fi
if [[ "$COMPOSE_SERVICE" == "<no value>" ]]; then
COMPOSE_SERVICE=""
fi
if [[ "$COMPOSE_CONFIG_FILES" == "<no value>" ]]; then
COMPOSE_CONFIG_FILES=""
fi
return 0
}
# ==============================================================================
# UPDATE COMPOSE INSTALLATION
# ==============================================================================
function update_compose() {
local workdir="$1"
local service="$2"
local config_files="$3"
local config
local -a configs=()
local -a compose_args=()
if [[ -n "$config_files" ]]; then
IFS=',' read -ra configs <<<"$config_files"
for config in "${configs[@]}"; do
compose_args+=(--file "$config")
done
fi
msg_info "Pulling latest ${APP} image"
cd "$INSTALL_PATH"
$STD docker compose pull
if [[ -n "$service" ]]; then
(cd "$workdir" && $STD docker compose "${compose_args[@]}" pull "$service")
else
(cd "$workdir" && $STD docker compose pull)
fi
msg_ok "Pulled latest image"
msg_info "Restarting ${APP}"
$STD docker compose up -d --remove-orphans
if [[ -n "$service" ]]; then
(cd "$workdir" && $STD docker compose "${compose_args[@]}" up -d "$service")
else
(cd "$workdir" && $STD docker compose up -d --remove-orphans)
fi
msg_ok "Restarted ${APP}"
}
# ==============================================================================
# UPDATE STANDALONE INSTALLATION
# ==============================================================================
function update_standalone() {
local old_image_id latest_image_id restart_name restart_max network_mode container_port host_ip host_port source destination mode writable
local was_running privileged user
local -a run_args=(-d --name portainer)
local -a command=()
old_image_id=$(docker inspect portainer --format '{{.Image}}')
was_running=$(docker inspect portainer --format '{{.State.Running}}')
restart_name=$(docker inspect portainer --format '{{.HostConfig.RestartPolicy.Name}}')
restart_max=$(docker inspect portainer --format '{{.HostConfig.RestartPolicy.MaximumRetryCount}}')
network_mode=$(docker inspect portainer --format '{{.HostConfig.NetworkMode}}')
privileged=$(docker inspect portainer --format '{{.HostConfig.Privileged}}')
user=$(docker inspect portainer --format '{{.Config.User}}')
if [[ -n "$restart_name" && "$restart_name" != "no" ]]; then
if [[ "$restart_name" == "on-failure" && "$restart_max" -gt 0 ]]; then
run_args+=(--restart "${restart_name}:${restart_max}")
else
run_args+=(--restart "$restart_name")
fi
fi
[[ "$network_mode" != "default" ]] && run_args+=(--network "$network_mode")
[[ "$privileged" == "true" ]] && run_args+=(--privileged)
[[ -n "$user" ]] && run_args+=(--user "$user")
while IFS='|' read -r container_port host_ip host_port; do
[[ -z "$container_port" || -z "$host_port" ]] && continue
[[ "$host_ip" == *:* ]] && host_ip="[${host_ip}]"
if [[ -n "$host_ip" && "$host_ip" != "0.0.0.0" ]]; then
run_args+=(-p "${host_ip}:${host_port}:${container_port}")
else
run_args+=(-p "${host_port}:${container_port}")
fi
done < <(docker inspect portainer --format '{{range $port, $bindings := .HostConfig.PortBindings}}{{range $bindings}}{{printf "%s|%s|%s\n" $port .HostIp .HostPort}}{{end}}{{end}}')
while IFS='|' read -r source destination mode writable; do
[[ -z "$source" || -z "$destination" ]] && continue
if [[ "$writable" == "false" ]]; then
mode="${mode:+${mode},}ro"
fi
run_args+=(-v "${source}:${destination}${mode:+:${mode}}")
done < <(docker inspect portainer --format '{{range .Mounts}}{{if eq .Type "volume"}}{{.Name}}{{else}}{{.Source}}{{end}}|{{.Destination}}|{{.Mode}}|{{.RW}}{{println}}{{end}}')
while IFS= read -r environment; do
[[ -n "$environment" ]] && run_args+=(-e "$environment")
done < <(docker inspect portainer --format '{{range .Config.Env}}{{println .}}{{end}}')
while IFS= read -r argument; do
[[ -n "$argument" ]] && command+=("$argument")
done < <(docker inspect portainer --format '{{range .Config.Cmd}}{{println .}}{{end}}')
msg_info "Pulling latest ${APP} image"
$STD docker pull "$PORTAINER_IMAGE"
latest_image_id=$(docker image inspect "$PORTAINER_IMAGE" --format '{{.Id}}')
msg_ok "Pulled latest image"
if [[ "$old_image_id" == "$latest_image_id" ]]; then
msg_ok "${APP} is already up to date"
return 0
fi
msg_info "Recreating ${APP}"
[[ "$was_running" == "true" ]] && $STD docker stop portainer
$STD docker rm portainer
if ! $STD docker run "${run_args[@]}" "$PORTAINER_IMAGE" "${command[@]}"; then
msg_warn "Update failed, restoring the previous ${APP} image"
docker rm -f portainer &>/dev/null || true
if $STD docker run "${run_args[@]}" "$old_image_id" "${command[@]}"; then
[[ "$was_running" != "true" ]] && $STD docker stop portainer
msg_error "Failed to update ${APP}; restored the previous container."
else
msg_error "Failed to update or restore ${APP}."
fi
exit 10
fi
msg_ok "Recreated ${APP}"
}
# ==============================================================================
# UPDATE
# ==============================================================================
function update() {
if [[ -f "$COMPOSE_FILE" ]]; then
update_compose "$INSTALL_PATH" "" ""
elif [[ -n "$COMPOSE_WORKDIR" && -n "$COMPOSE_SERVICE" && -d "$COMPOSE_WORKDIR" ]]; then
update_compose "$COMPOSE_WORKDIR" "$COMPOSE_SERVICE" "$COMPOSE_CONFIG_FILES"
else
update_standalone
fi
ensure_update_script
msg_ok "Updated successfully"
exit
@@ -81,26 +252,16 @@ function check_docker() {
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
}
# ==============================================================================
# CHECK EXISTING CONTAINER
# ==============================================================================
function check_existing_container() {
# Guards against clobbering a Portainer container not managed by this addon
# (e.g. Business/Enterprise Edition installed manually or via the legacy docker.sh flow)
if docker ps -a --format '{{.Names}}' | grep -q '^portainer$'; then
msg_error "A container named 'portainer' already exists but is not managed by this addon."
msg_error "This may be a Portainer Business/Enterprise Edition install or a manual setup."
msg_error "Remove/rename that container first, or manage it manually. Exiting."
exit 10
fi
}
# ==============================================================================
# INSTALL
# ==============================================================================
function install() {
check_docker
check_existing_container
detect_portainer
if [[ -n "$PORTAINER_IMAGE" ]]; then
msg_error "${APP} is already installed."
exit 10
fi
msg_info "Creating install directory"
mkdir -p "$INSTALL_PATH"
@@ -115,15 +276,7 @@ function install() {
$STD docker compose up -d
msg_ok "Started ${APP}"
# Create update script
msg_info "Creating update script"
cat <<'UPDATEEOF' >/usr/local/bin/update_portainer
#!/usr/bin/env bash
# Portainer Update Script
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/portainer.sh)"
UPDATEEOF
chmod +x /usr/local/bin/update_portainer
msg_ok "Created update script (/usr/local/bin/update_portainer)"
ensure_update_script
echo ""
msg_ok "${APP} is reachable at: ${BL}https://${LOCAL_IP}:${DEFAULT_PORT}${CL}"
@@ -138,7 +291,9 @@ UPDATEEOF
# Handle type=update (called from update script)
if [[ "${type:-}" == "update" ]]; then
header_info
if [[ -f "$COMPOSE_FILE" ]]; then
check_docker
detect_portainer
if [[ -f "$COMPOSE_FILE" || -n "$PORTAINER_IMAGE" ]]; then
update
else
msg_error "${APP} is not installed. Nothing to update."
@@ -150,16 +305,21 @@ fi
header_info
get_lxc_ip
check_docker
detect_portainer
# Check if already installed
if [[ -f "$COMPOSE_FILE" ]]; then
if [[ -f "$COMPOSE_FILE" || -n "$PORTAINER_IMAGE" ]]; then
msg_warn "${APP} is already installed."
echo ""
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
if [[ -f "$COMPOSE_FILE" ]]; then
echo -n "${TAB}Uninstall ${APP}? (y/N): "
read -r uninstall_prompt
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
uninstall
exit 0
fi
fi
echo -n "${TAB}Update ${APP}? (y/N): "
+422
View File
@@ -0,0 +1,422 @@
#!/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
header_info() {
clear
cat <<"EOF"
____ ____ __ ___ ____ __ ____ __ ____
/ __ \/ __ \/ |/ / / __ \____ _____/ /_ / _/___ _____/ /_____ _/ / /
/ /_/ / / / / /|_/ / / /_/ / __ \/ ___/ __/ / // __ \/ ___/ __/ __ `/ / /
/ ____/ /_/ / / / / / ____/ /_/ (__ ) /_ _/ // / / (__ ) /_/ /_/ / / /
/_/ /_____/_/ /_/ /_/ \____/____/\__/ /___/_/ /_/____/\__/\__,_/_/_/
EOF
}
RD=$(echo "\033[01;31m")
YW=$(echo "\033[33m")
GN=$(echo "\033[1;92m")
CL=$(echo "\033[m")
BFR="\\r\\033[K"
HOLD="-"
CM="${GN}${CL}"
CROSS="${RD}${CL}"
set -euo pipefail
shopt -s inherit_errexit nullglob
msg_info() {
local msg="$1"
echo -ne " ${HOLD} ${YW}${msg}..."
}
msg_ok() {
local msg="$1"
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
}
msg_error() {
local msg="$1"
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
}
# Telemetry
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pdm-install" "pve"
if ! dpkg -s proxmox-datacenter-manager >/dev/null 2>&1; then
msg_error "This script is only intended for Proxmox Datacenter Manager"
exit 232
fi
repo_state() {
# $1 = component name (e.g. pdm-enterprise, pdm-no-subscription, pdm-test)
local repo="$1"
local file=""
local state="missing"
for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; do
[[ -f "$f" ]] || continue
if grep -q "$repo" "$f"; then
file="$f"
if [[ "$f" == *.sources ]]; then
if grep -qiE '^Enabled:\s*(no|false)' "$f"; then
state="disabled"
else
state="active"
fi
else
if grep -qE "^[^#].*${repo}" "$f"; then
state="active"
elif grep -qE "^#.*${repo}" "$f"; then
state="disabled"
fi
fi
break
fi
done
echo "$state $file"
}
toggle_repo() {
# $1 = file, $2 = action (enable|disable)
local file="$1" action="$2"
if [[ "$file" == *.sources ]]; then
if [[ "$action" == "disable" ]]; then
if grep -qiE '^Enabled:' "$file"; then
sed -i 's/^Enabled:.*/Enabled: false/' "$file"
else
echo "Enabled: false" >>"$file"
fi
else
sed -i 's/^Enabled:.*/Enabled: true/' "$file"
fi
else
if [[ "$action" == "disable" ]]; then
sed -i '/^[^#]/s/^/# /' "$file"
else
sed -i 's/^# *//' "$file"
fi
fi
}
start_routines() {
header_info
VERSION="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
# ---- SOURCES ----
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM SOURCES" --menu \
"This will set the correct Debian sources for Proxmox Datacenter Manager.\n\nCorrect sources?" 14 58 2 \
"yes" " " \
"no" " " 3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Correcting Debian Sources"
cat <<EOF >/etc/apt/sources.list.d/debian.sources
Types: deb
URIs: http://deb.debian.org/debian/
Suites: ${VERSION} ${VERSION}-updates
Components: main contrib non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: http://security.debian.org/debian-security/
Suites: ${VERSION}-security
Components: main contrib non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
EOF
rm -f /etc/apt/sources.list
msg_ok "Corrected Debian Sources"
;;
no) msg_error "Selected no to Correcting Debian Sources" ;;
esac
# ---- PDM-ENTERPRISE ----
read -r state file <<<"$(repo_state pdm-enterprise)"
case $state in
active)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-ENTERPRISE" \
--menu "'pdm-enterprise' repository is currently ENABLED.\n\nIt requires a subscription and will fail apt update without one.\n\nWhat do you want to do?" 16 58 3 \
"disable" "Disable this repo" \
"keep" "Keep as is" \
"delete" "Delete repo file" \
3>&2 2>&1 1>&3)
case $CHOICE in
keep) msg_ok "Kept 'pdm-enterprise' repository" ;;
disable)
msg_info "Disabling 'pdm-enterprise' repository"
toggle_repo "$file" disable
msg_ok "Disabled 'pdm-enterprise' repository"
;;
delete)
msg_info "Deleting 'pdm-enterprise' repository file"
rm -f "$file"
msg_ok "Deleted 'pdm-enterprise' repository file"
;;
esac
;;
disabled)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-ENTERPRISE" \
--menu "'pdm-enterprise' repository is currently DISABLED.\n\nWhat do you want to do?" 14 58 3 \
"keep" "Keep disabled" \
"enable" "Enable (subscription required)" \
"delete" "Delete repo file" \
3>&2 2>&1 1>&3)
case $CHOICE in
enable)
msg_info "Enabling 'pdm-enterprise' repository"
toggle_repo "$file" enable
msg_ok "Enabled 'pdm-enterprise' repository"
;;
keep) msg_ok "Kept 'pdm-enterprise' repository disabled" ;;
delete)
msg_info "Deleting 'pdm-enterprise' repository file"
rm -f "$file"
msg_ok "Deleted 'pdm-enterprise' repository file"
;;
esac
;;
missing)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-ENTERPRISE" \
--menu "Add 'pdm-enterprise' repository?\n\nOnly for subscription customers." 14 58 2 \
"no" " " \
"yes" " " \
--default-item "no" \
3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Adding 'pdm-enterprise' repository"
cat <<EOF >/etc/apt/sources.list.d/pdm-enterprise.sources
Types: deb
URIs: https://enterprise.proxmox.com/debian/pdm
Suites: ${VERSION}
Components: pdm-enterprise
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF
msg_ok "Added 'pdm-enterprise' repository"
;;
no) msg_error "Selected no to Adding 'pdm-enterprise' repository" ;;
esac
;;
esac
# ---- PDM-NO-SUBSCRIPTION ----
read -r state file <<<"$(repo_state pdm-no-subscription)"
case $state in
active)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-NO-SUBSCRIPTION" \
--menu "'pdm-no-subscription' repository is currently ENABLED.\n\nWhat do you want to do?" 14 58 3 \
"keep" "Keep as is" \
"disable" "Disable this repo" \
"delete" "Delete repo file" \
3>&2 2>&1 1>&3)
case $CHOICE in
keep) msg_ok "Kept 'pdm-no-subscription' repository" ;;
disable)
msg_info "Disabling 'pdm-no-subscription' repository"
toggle_repo "$file" disable
msg_ok "Disabled 'pdm-no-subscription' repository"
;;
delete)
msg_info "Deleting 'pdm-no-subscription' repository file"
rm -f "$file"
msg_ok "Deleted 'pdm-no-subscription' repository file"
;;
esac
;;
disabled)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-NO-SUBSCRIPTION" \
--menu "'pdm-no-subscription' repository is currently DISABLED.\n\nWhat do you want to do?" 14 58 3 \
"enable" "Enable (recommended)" \
"keep" "Keep disabled" \
"delete" "Delete repo file" \
3>&2 2>&1 1>&3)
case $CHOICE in
enable)
msg_info "Enabling 'pdm-no-subscription' repository"
toggle_repo "$file" enable
msg_ok "Enabled 'pdm-no-subscription' repository"
;;
keep) msg_ok "Kept 'pdm-no-subscription' repository disabled" ;;
delete)
msg_info "Deleting 'pdm-no-subscription' repository file"
rm -f "$file"
msg_ok "Deleted 'pdm-no-subscription' repository file"
;;
esac
;;
missing)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-NO-SUBSCRIPTION" \
--menu "The 'pdm-no-subscription' repository provides access to all open-source components of Proxmox Datacenter Manager.\n\nAdd 'pdm-no-subscription' repository?" 14 58 2 \
"yes" " " \
"no" " " \
3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Adding 'pdm-no-subscription' repository"
cat <<EOF >/etc/apt/sources.list.d/proxmox.sources
Types: deb
URIs: http://download.proxmox.com/debian/pdm
Suites: ${VERSION}
Components: pdm-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF
msg_ok "Added 'pdm-no-subscription' repository"
;;
no) msg_error "Selected no to Adding 'pdm-no-subscription' repository" ;;
esac
;;
esac
# ---- PDM-TEST ----
read -r state file <<<"$(repo_state pdm-test)"
case $state in
active) msg_ok "'pdm-test' repository already active (skipped)" ;;
disabled) msg_ok "'pdm-test' repository already disabled (skipped)" ;;
missing)
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PDM-TEST" \
--menu "The 'pdm-test' repository is used by developers to test new features.\n\nAdd (disabled) 'pdm-test' repository?" 14 58 2 \
"yes" " " \
"no" " " 3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Adding 'pdm-test' repository (disabled)"
cat <<EOF >/etc/apt/sources.list.d/pdm-test.sources
Types: deb
URIs: http://download.proxmox.com/debian/pdm
Suites: ${VERSION}
Components: pdm-test
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
Enabled: false
EOF
msg_ok "Added 'pdm-test' repository"
;;
no) msg_error "Selected no to Adding 'pdm-test' repository" ;;
esac
;;
esac
# ---- SUBSCRIPTION NAG ----
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SUBSCRIPTION NAG" --menu \
"Disable subscription nag in the PDM UI?" 14 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
case $CHOICE in
yes)
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Support Subscriptions" \
"Supporting the software's development team is essential.\nPlease consider buying a subscription." 10 58
msg_info "Disabling subscription nag"
mkdir -p /usr/local/bin
cat <<'EOF' >/usr/local/bin/pdm-remove-nag.sh
#!/bin/sh
# PDM ships its web UI as a Yew/WASM app in a single JS bundle - there is no
# proxmoxlib.js and no HTML template to patch, so the dialog is confirmed at
# runtime instead. The nag gates the update refresh: its on_close callback is
# what sends RefreshAll, so it must be close()d, never removed from the DOM.
# Re-applied by the apt hook after every package update.
BUNDLE=/usr/share/javascript/proxmox-datacenter-manager/js/pdm-ui_bundle.js
if [ -s "$BUNDLE" ] && ! grep -q PDM_NO_MORE_NAGGING "$BUNDLE"; then
echo "Patching PDM subscription nag..."
cat >>"$BUNDLE" <<'JS'
// PDM_NO_MORE_NAGGING
(function () {
var MARK = 'data-pdm-nag';
var dismiss = function (d) {
if (d.getAttribute(MARK)) return;
d.setAttribute(MARK, '1');
var tries = 12;
var tick = function () {
if (!d.isConnected || tries-- <= 0) return;
try { d.close(); } catch (e) {}
setTimeout(tick, 120);
};
requestAnimationFrame(tick);
};
var scan = function () {
document.querySelectorAll('dialog.pwt-outer-dialog').forEach(function (d) {
if ((d.textContent || '').indexOf('pdm.proxmox.com') !== -1) dismiss(d);
});
};
var start = function () {
scan();
new MutationObserver(scan).observe(document.body, { childList: true, subtree: true });
};
if (document.body) { start(); } else {
document.addEventListener('DOMContentLoaded', start);
}
})();
JS
fi
EOF
chmod 755 /usr/local/bin/pdm-remove-nag.sh
/usr/local/bin/pdm-remove-nag.sh >/dev/null 2>&1
cat <<'EOF' >/etc/apt/apt.conf.d/no-nag-script
DPkg::Post-Invoke { "/usr/local/bin/pdm-remove-nag.sh"; };
EOF
chmod 644 /etc/apt/apt.conf.d/no-nag-script
msg_ok "Disabled subscription nag (clear browser cache!)"
;;
no)
msg_error "Selected no to Disabling subscription nag"
rm -f /etc/apt/apt.conf.d/no-nag-script /usr/local/bin/pdm-remove-nag.sh 2>/dev/null
apt --reinstall install proxmox-datacenter-manager-ui &>/dev/null || msg_error "UI reinstall failed"
;;
esac
# ---- UPDATE ----
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UPDATE" --menu \
"Update Proxmox Datacenter Manager now?" 11 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Updating Proxmox Datacenter Manager (Patience)"
apt update &>/dev/null || msg_error "apt update failed"
apt -y dist-upgrade &>/dev/null || msg_error "apt dist-upgrade failed"
msg_ok "Updated Proxmox Datacenter Manager"
;;
no) msg_error "Selected no to updating Proxmox Datacenter Manager" ;;
esac
# ---- REMINDER ----
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Post-Install Reminder" --msgbox \
"IMPORTANT:
Proxmox Datacenter Manager is still under active development. Do not rely on it as the only management path to your nodes.
After completing these steps, it is strongly recommended to REBOOT.
After the upgrade or post-install routines, always clear your browser cache or perform a hard reload (Ctrl+Shift+R) before using the PDM Web UI to avoid UI display issues." 20 80
# ---- REBOOT ----
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "REBOOT" --menu \
"Reboot Proxmox Datacenter Manager now? (recommended)" 11 58 2 "yes" " " "no" " " 3>&2 2>&1 1>&3)
case $CHOICE in
yes)
msg_info "Rebooting Proxmox Datacenter Manager"
sleep 2
msg_ok "Completed Post Install Routines"
reboot
;;
no)
msg_error "Selected no to reboot (Reboot recommended)"
msg_ok "Completed Post Install Routines"
;;
esac
}
header_info
echo -e "\nThis script will Perform Post Install Routines.\n"
while true; do
read -rp "Start the Proxmox Datacenter Manager Post Install Script (y/n)? " yn
case $yn in
[Yy]*) break ;;
[Nn]*)
clear
exit
;;
*) echo "Please answer yes or no." ;;
esac
done
start_routines
-12
View File
@@ -125,12 +125,6 @@ EOF
no) msg_error "Selected no to Correcting Proxmox VE Sources" ;;
esac
if [[ "$(dpkg --print-architecture 2>/dev/null)" == "arm64" ]]; then
msg_ok "ARM64 detected - skipping Proxmox repository setup"
post_routines_common
return
fi
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PVE-ENTERPRISE" --menu "The 'pve-enterprise' repository is only available to users who have purchased a Proxmox VE subscription.\n \nDisable 'pve-enterprise' repository?" 14 58 2 \
"yes" " " \
"no" " " 3>&2 2>&1 1>&3)
@@ -288,12 +282,6 @@ EOF
esac
fi
if [[ "$(dpkg --print-architecture 2>/dev/null)" == "arm64" ]]; then
msg_ok "ARM64 detected - skipping Proxmox repository setup"
post_routines_common
return
fi
# ---- PVE-ENTERPRISE ----
if component_exists_in_sources "pve-enterprise"; then
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" \