mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-10-23 11:45:03 +00:00
Compare commits
70
Commits
2026-08-03
...
2026-08-08
No files matched your search
Generated
+139
@@ -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
|
||||
|
||||
+2
@@ -6,6 +6,8 @@ on:
|
||||
- main
|
||||
paths:
|
||||
- "ct/**.sh"
|
||||
- "tools/**.sh"
|
||||
- "vm/**.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
Generated
+18
-2
@@ -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) };
|
||||
}
|
||||
|
||||
Generated
+25
-6
@@ -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
@@ -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;
|
||||
|
||||
+3
-1
@@ -24,7 +24,9 @@ generate_headers() {
|
||||
|
||||
app_name=$(grep -oP '^APP="\K[^"]+' "$script" 2>/dev/null)
|
||||
if [[ -n "$app_name" ]]; then
|
||||
output_file="${headers_dir}/$(basename "${script%.*}")"
|
||||
# core.func/vm-core.func look the header up as "${APP,,}" without spaces,
|
||||
# so the generated file has to be named after APP - not after the script.
|
||||
output_file="${headers_dir}/$(echo "${app_name,,}" | tr -d ' ')"
|
||||
figlet_output=$(figlet -w 500 -f slant "$app_name")
|
||||
if [[ -n "$figlet_output" ]]; then
|
||||
echo "$figlet_output" >"$output_file"
|
||||
|
||||
+111
-92
@@ -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,112 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
</details>
|
||||
|
||||
## 2026-08-09
|
||||
|
||||
## 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
|
||||
@@ -1062,94 +1171,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))
|
||||
@@ -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)**
|
||||
|
||||
|
||||
+3
-1
@@ -30,7 +30,7 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
RELEASE=$(get_latest_github_release "actualbudget/actual")
|
||||
if [[ -f /opt/actualbudget-data/config.json ]]; then
|
||||
if check_for_gh_release "actualbudget" "actualbudget/actual"; then
|
||||
@@ -39,7 +39,9 @@ function update_script() {
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Updating Actual Budget to ${RELEASE}"
|
||||
$STD npm config set allow-scripts=bcrypt,better-sqlite3,argon2 --location=global
|
||||
$STD npm update -g @actual-app/sync-server
|
||||
$STD npm rebuild -g
|
||||
echo "${RELEASE}" >~/.actualbudget
|
||||
msg_ok "Updated Actual Budget to ${RELEASE}"
|
||||
|
||||
|
||||
@@ -81,6 +81,8 @@ TURBO
|
||||
|
||||
export NODE_OPTIONS="--max-old-space-size=2048"
|
||||
$STD yarn install
|
||||
$STD bash ./scripts/set-version.sh "$(cat ~/.affine_app)"
|
||||
export BUILD_TYPE=stable
|
||||
$STD npm install -g typescript
|
||||
|
||||
$STD yarn affine @affine/native build
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
__ ___ __
|
||||
/ / / (_)____/ /____ _____
|
||||
/ /_/ / / ___/ __/ _ \/ ___/
|
||||
/ __ / (__ ) /_/ __/ /
|
||||
/_/ /_/_/____/\__/\___/_/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
____ _
|
||||
/ _/___ _____ (_)____
|
||||
/ // __ `/ __ \/ / ___/
|
||||
_/ // /_/ / / / / (__ )
|
||||
/___/\__, /_/ /_/_/____/
|
||||
/____/
|
||||
File renamed without changes.
@@ -1,6 +0,0 @@
|
||||
_____
|
||||
/ ___/_________ _____ ____ ____ __ __
|
||||
\__ \/ ___/ __ `/ __ \/ __ \/ __ \/ / / /
|
||||
___/ / /__/ /_/ / / / / /_/ / /_/ / /_/ /
|
||||
/____/\___/\__,_/_/ /_/\____/ .___/\__, /
|
||||
/_/ /____/
|
||||
@@ -0,0 +1,6 @@
|
||||
_ __ __ __ ____ __ _ _
|
||||
/ | / /__ / /__ ______ _____/ /__/ __ \____ / /_(_)___ ___ (_)___ ___ _____
|
||||
/ |/ / _ \/ __/ | /| / / __ \/ ___/ //_/ / / / __ \/ __/ / __ `__ \/ /_ / / _ \/ ___/
|
||||
/ /| / __/ /_ | |/ |/ / /_/ / / / ,< / /_/ / /_/ / /_/ / / / / / / / / /_/ __/ /
|
||||
/_/ |_/\___/\__/ |__/|__/\____/_/ /_/|_|\____/ .___/\__/_/_/ /_/ /_/_/ /___/\___/_/
|
||||
/_/
|
||||
@@ -0,0 +1,6 @@
|
||||
____ __ _ ___ __ _ _____
|
||||
/ __ \/ /_ _____(_)___/ (_)___ _____ / / (_) _____ / ___/__ ______ _____
|
||||
/ / / / __ \/ ___/ / __ / / __ `/ __ \______/ / / / | / / _ \\__ \/ / / / __ \/ ___/
|
||||
/ /_/ / /_/ (__ ) / /_/ / / /_/ / / / /_____/ /___/ /| |/ / __/__/ / /_/ / / / / /__
|
||||
\____/_.___/____/_/\__,_/_/\__,_/_/ /_/ /_____/_/ |___/\___/____/\__, /_/ /_/\___/
|
||||
/____/
|
||||
@@ -0,0 +1,6 @@
|
||||
____ __
|
||||
/ __ \_____/ /_
|
||||
/ / / / ___/ __ \
|
||||
/ /_/ / / / /_/ /
|
||||
\____/_/ /_.___/
|
||||
|
||||
@@ -46,8 +46,11 @@ function update_script() {
|
||||
|
||||
msg_info "Updating Heimdall-Dashboard"
|
||||
cd /opt/Heimdall
|
||||
sed -i 's/^APP_ENV=.*/APP_ENV=production/' .env
|
||||
rm -f bootstrap/cache/*.php
|
||||
export COMPOSER_ALLOW_SUPERUSER=1
|
||||
$STD composer dump-autoload
|
||||
$STD composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
|
||||
$STD php artisan optimize:clear
|
||||
msg_ok "Updated Heimdall-Dashboard"
|
||||
|
||||
msg_info "Restoring Data"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/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/asciimoo/hister
|
||||
|
||||
APP="Hister"
|
||||
var_tags="${var_tags:-search;browser-history;personal}"
|
||||
var_cpu="${var_cpu:-1}"
|
||||
var_ram="${var_ram:-1024}"
|
||||
var_disk="${var_disk:-20}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-yes}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -f /usr/local/bin/hister ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_release "hister" "asciimoo/hister"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop hister
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
fetch_and_deploy_gh_release "hister" "asciimoo/hister" "singlefile" "latest" "/usr/local/bin" "hister_*_linux_$(arch_resolve)"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start hister
|
||||
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}:4433${CL}"
|
||||
+36
-9
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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}"
|
||||
+1
-1
@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_disk="${var_disk:-8}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-12}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-yes}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/vrtmrz/obsidian-livesync | https://couchdb.apache.org/
|
||||
|
||||
APP="Obsidian-LiveSync"
|
||||
var_tags="${var_tags:-documents;notes}"
|
||||
var_cpu="${var_cpu:-1}"
|
||||
var_ram="${var_ram:-1024}"
|
||||
var_disk="${var_disk:-8}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_arm64="${var_arm64:-yes}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -f /opt/couchdb/etc/local.d/obsidian-livesync.ini ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
msg_info "Stopping CouchDB"
|
||||
systemctl stop couchdb
|
||||
msg_ok "Stopped CouchDB"
|
||||
|
||||
create_backup /var/lib/couchdb /opt/couchdb/etc/local.d/obsidian-livesync.ini /opt/obsidian-livesync/.env
|
||||
|
||||
msg_info "Updating Container OS"
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
msg_ok "Updated Container OS"
|
||||
|
||||
systemctl stop couchdb
|
||||
restore_backup
|
||||
|
||||
msg_info "Starting CouchDB"
|
||||
systemctl start couchdb
|
||||
msg_ok "Started CouchDB"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW}Configure the Self-hosted LiveSync plugin with the credentials in /opt/obsidian-livesync/.env${CL}"
|
||||
echo -e "${GATEWAY}${BGN}http://${IP}:5984/_utils/${CL}"
|
||||
@@ -43,6 +43,8 @@ function update_script() {
|
||||
fi
|
||||
msg_ok "New version available: ${LATEST}"
|
||||
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop omniroute
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
RELEASE="v7.3.0"
|
||||
RELEASE="v7.4.0"
|
||||
if check_for_gh_release "OpenCloud" "opencloud-eu/opencloud" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
|
||||
msg_info "Stopping services"
|
||||
systemctl stop opencloud opencloud-wopi
|
||||
|
||||
@@ -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}"
|
||||
@@ -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
-1
@@ -65,7 +65,7 @@ function update_script() {
|
||||
read -rp "Do you want to continue with the update? (y/N): " MIGRATE
|
||||
echo
|
||||
if [[ ! "$MIGRATE" =~ ^[Yy]$ ]]; then
|
||||
msg_info "Update aborted. Decrypt all documents before upgrading to v3."
|
||||
msg_custom "⚠️" "Update aborted. Decrypt all documents before upgrading to v3."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -38,6 +38,7 @@ function update_script() {
|
||||
create_backup /opt/passwordpusher/storage /opt/passwordpusher/.env.production
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball"
|
||||
RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
|
||||
msg_info "Installing Gem Dependencies"
|
||||
cd /opt/passwordpusher
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ function update_script() {
|
||||
sed -i "s/^\(Pin: version \).*/\1${RELEASE}/" /etc/apt/preferences.d/salt-pin-1001
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
echo "${RELEASE}" >/~.salt
|
||||
echo "${RELEASE}" >~/.salt
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
exit
|
||||
|
||||
+38
-10
@@ -112,14 +112,33 @@ EOF
|
||||
msg_ok "Stopped Termix"
|
||||
|
||||
msg_info "Migrating Configuration"
|
||||
if [[ ! -f /opt/termix/.env ]]; then
|
||||
cat <<EOF >/opt/termix/.env
|
||||
mkdir -p /opt/termix/db/data
|
||||
|
||||
if [[ -f /opt/termix/data/db.sqlite.encrypted && ! -f /opt/termix/db/data/db.sqlite.encrypted ]]; then
|
||||
cp -a /opt/termix/data/db.sqlite.encrypted /opt/termix/db/data/db.sqlite.encrypted
|
||||
[[ -f /opt/termix/data/db.sqlite.encrypted.meta ]] &&
|
||||
cp -a /opt/termix/data/db.sqlite.encrypted.meta /opt/termix/db/data/db.sqlite.encrypted.meta
|
||||
[[ -f /opt/termix/data/db.sqlite ]] &&
|
||||
cp -a /opt/termix/data/db.sqlite /opt/termix/db/data/db.sqlite
|
||||
fi
|
||||
|
||||
if [[ -f /opt/termix/data/.env && ! -f /opt/termix/db/data/.env ]]; then
|
||||
cp -a /opt/termix/data/.env /opt/termix/db/data/.env
|
||||
fi
|
||||
|
||||
for sub in ssl session_logs session_recordings acme-webroot certbot uploads; do
|
||||
if [[ -d /opt/termix/data/$sub && ! -d /opt/termix/db/data/$sub ]]; then
|
||||
cp -a "/opt/termix/data/$sub" "/opt/termix/db/data/$sub"
|
||||
fi
|
||||
done
|
||||
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
DATA_DIR=/opt/termix/db/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
fi
|
||||
|
||||
if ! grep -q "EnvironmentFile" /etc/systemd/system/termix.service 2>/dev/null; then
|
||||
cat <<EOF >/etc/systemd/system/termix.service
|
||||
[Unit]
|
||||
@@ -143,7 +162,11 @@ EOF
|
||||
fi
|
||||
msg_ok "Migrated Configuration"
|
||||
|
||||
create_backup /opt/termix/data /opt/termix/uploads /opt/termix/.env
|
||||
create_backup \
|
||||
/opt/termix/db/data \
|
||||
/opt/termix/data \
|
||||
/opt/termix/uploads \
|
||||
/opt/termix/.env
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix" "tarball"
|
||||
|
||||
@@ -158,10 +181,10 @@ EOF
|
||||
/opt/termix/db/data
|
||||
msg_ok "Recreated Directories"
|
||||
|
||||
if [[ -f /opt/termix/data/db.sqlite.encrypted && ! -f /opt/termix/db/data/db.sqlite.encrypted ]]; then
|
||||
msg_info "Migrating Database to new layout"
|
||||
cp -a /opt/termix/data/db.sqlite.encrypted /opt/termix/db/data/db.sqlite.encrypted
|
||||
msg_ok "Migrated Database to new layout"
|
||||
if [[ -f /opt/termix/db/data/db.sqlite.encrypted && ! -f /opt/termix/db/data/.env ]]; then
|
||||
msg_error "Encrypted database restored without its keys (/opt/termix/db/data/.env is missing)"
|
||||
msg_custom "🛟" "Restore the container from a backup and report this at https://github.com/community-scripts/ProxmoxVE/issues"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg_info "Building Frontend"
|
||||
@@ -237,7 +260,12 @@ EOF
|
||||
fi
|
||||
|
||||
msg_info "Starting Termix"
|
||||
systemctl start termix
|
||||
systemctl daemon-reload
|
||||
if ! systemctl start termix; then
|
||||
msg_error "Termix failed to start"
|
||||
journalctl -u termix -n 30 --no-pager || true
|
||||
exit 1
|
||||
fi
|
||||
msg_ok "Started Termix"
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
|
||||
+2
-3
@@ -46,8 +46,7 @@ function update_script() {
|
||||
[[ "$CONFIRM2" =~ ^[yY]$ ]] || exit 0
|
||||
fi
|
||||
|
||||
RELEASE="v2.3.0"
|
||||
if check_for_gh_release "vikunja" "go-vikunja/vikunja" "${RELEASE}" "v2.4.0 is killed at startup by the systemd SystemCallFilter shipped in the .deb (upstream go-vikunja/vikunja#3252); pinned until a fixed release is out"; then
|
||||
if check_for_gh_release "vikunja" "go-vikunja/vikunja"; then
|
||||
echo
|
||||
msg_warn "The package update may include config file changes."
|
||||
echo -e "${TAB}${YW}How do you want to handle /etc/vikunja/config.yml?${CL}"
|
||||
@@ -66,7 +65,7 @@ function update_script() {
|
||||
systemctl stop vikunja
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary" "${RELEASE}" "" "vikunja-*-$(arch_resolve "x86_64" "aarch64").deb"
|
||||
fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary" "latest" "" "vikunja-*-$(arch_resolve "x86_64" "aarch64").deb"
|
||||
$STD systemctl daemon-reload
|
||||
|
||||
msg_info "Starting Service"
|
||||
|
||||
@@ -34,6 +34,8 @@ function update_script() {
|
||||
systemctl stop watcharr
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
|
||||
create_backup /opt/watcharr/server/data
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "watcharr" "sbondCo/Watcharr" "tarball"
|
||||
restore_backup
|
||||
|
||||
@@ -48,6 +48,13 @@ function update_script() {
|
||||
chmod 644 /opt/xyops/node_modules/useragent-ng/lib/regexps.js
|
||||
msg_ok "Rebuilt Application"
|
||||
|
||||
fetch_and_deploy_gh_release "xysat" "pixlcore/xysat" "tarball" "latest" "/opt/xyops/satellite"
|
||||
|
||||
msg_info "Building xySat Satellite"
|
||||
cd /opt/xyops/satellite
|
||||
$STD npm install
|
||||
msg_ok "Built xySat Satellite"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start xyops
|
||||
msg_ok "Started Service"
|
||||
|
||||
@@ -19,7 +19,7 @@ $STD apt install -y \
|
||||
g++
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
create_self_signed_cert
|
||||
|
||||
msg_info "Installing Actual Budget"
|
||||
@@ -51,6 +51,7 @@ cat <<EOF >/opt/actualbudget-data/config.json
|
||||
EOF
|
||||
mkdir -p /opt/actualbudget
|
||||
cd /opt/actualbudget
|
||||
$STD npm config set allow-scripts=bcrypt,better-sqlite3,argon2 --location=global
|
||||
$STD npm install --location=global @actual-app/sync-server
|
||||
echo "${RELEASE}" >~/.actualbudget
|
||||
msg_ok "Installed Actual Budget"
|
||||
|
||||
@@ -78,6 +78,8 @@ $STD yarn config set enableTelemetry 0
|
||||
export NODE_OPTIONS="--max-old-space-size=4096"
|
||||
export TSC_COMPILE_ON_ERROR=true
|
||||
$STD yarn install
|
||||
$STD bash ./scripts/set-version.sh "$(cat ~/.affine_app)"
|
||||
export BUILD_TYPE=stable
|
||||
$STD npm install -g typescript
|
||||
$STD yarn affine @affine/native build
|
||||
$STD yarn affine @affine/server-native build
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,6 +24,7 @@ fetch_and_deploy_gh_release "Heimdall" "linuxserver/Heimdall" "tarball"
|
||||
msg_info "Setting up Heimdall-Dashboard"
|
||||
cd /opt/Heimdall
|
||||
cp .env.example .env
|
||||
sed -i 's/^APP_ENV=.*/APP_ENV=production/' .env
|
||||
$STD php artisan key:generate
|
||||
msg_ok "Setup Heimdall-Dashboard"
|
||||
|
||||
|
||||
@@ -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://github.com/asciimoo/hister
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
fetch_and_deploy_gh_release "hister" "asciimoo/hister" "singlefile" "latest" "/usr/local/bin" "hister_*_linux_$(arch_resolve)"
|
||||
|
||||
msg_info "Configuring Hister"
|
||||
mkdir -p /opt/hister/data /etc/hister
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
cat <<EOF >/etc/hister/config.yaml
|
||||
app:
|
||||
directory: '/opt/hister/data'
|
||||
server:
|
||||
address: '0.0.0.0:4433'
|
||||
base_url: 'http://${LOCAL_IP}:4433'
|
||||
EOF
|
||||
msg_ok "Configured Hister"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/hister.service
|
||||
[Unit]
|
||||
Description=Hister Search Engine
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/usr/local/bin/hister listen --config /etc/hister/config.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now hister
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -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);")
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -24,6 +24,16 @@ if [[ ! "$CONFIRM" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Making ssh.service reloads behave like restarts"
|
||||
mkdir -p /etc/systemd/system/ssh.service.d
|
||||
cat <<'EOF' >/etc/systemd/system/ssh.service.d/reload-as-restart.conf
|
||||
[Service]
|
||||
ExecReload=
|
||||
ExecReload=/usr/bin/systemd-run --no-block --quiet /bin/systemctl restart ssh.service
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
msg_ok "Made ssh.service reloads behave like restarts"
|
||||
|
||||
msg_info "Installing NextCloudPi (Patience)"
|
||||
$STD bash <(curl -fsSL https://raw.githubusercontent.com/nextcloud/nextcloudpi/master/install.sh)
|
||||
msg_ok "Installed NextCloudPi"
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/vrtmrz/obsidian-livesync | https://couchdb.apache.org/
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
setup_deb822_repo \
|
||||
"couchdb" \
|
||||
"https://couchdb.apache.org/repo/keys.asc" \
|
||||
"https://apache.jfrog.io/artifactory/couchdb-deb/" \
|
||||
"$(get_os_info codename)" \
|
||||
"main"
|
||||
|
||||
msg_info "Installing CouchDB"
|
||||
COUCHDB_ADMIN_USER="admin"
|
||||
COUCHDB_PASSWORD="$(openssl rand -hex 24)"
|
||||
COUCHDB_COOKIE="$(openssl rand -hex 16)"
|
||||
|
||||
cat <<EOF | debconf-set-selections
|
||||
couchdb couchdb/mode select standalone
|
||||
couchdb couchdb/mode seen true
|
||||
couchdb couchdb/bindaddress string 0.0.0.0
|
||||
couchdb couchdb/bindaddress seen true
|
||||
couchdb couchdb/cookie string ${COUCHDB_COOKIE}
|
||||
couchdb couchdb/cookie seen true
|
||||
couchdb couchdb/adminpass password ${COUCHDB_PASSWORD}
|
||||
couchdb couchdb/adminpass seen true
|
||||
couchdb couchdb/adminpass_again password ${COUCHDB_PASSWORD}
|
||||
couchdb couchdb/adminpass_again seen true
|
||||
EOF
|
||||
DEBIAN_FRONTEND=noninteractive $STD apt-get install -y couchdb
|
||||
|
||||
cat <<EOF >/root/.couchdb.credentials
|
||||
COUCHDB_ADMIN_USER="${COUCHDB_ADMIN_USER}"
|
||||
COUCHDB_ADMIN_PASSWORD="${COUCHDB_PASSWORD}"
|
||||
COUCHDB_COOKIE="${COUCHDB_COOKIE}"
|
||||
EOF
|
||||
msg_ok "Installed CouchDB"
|
||||
|
||||
msg_info "Configuring CouchDB"
|
||||
mkdir -p /opt/couchdb/etc/local.d /opt/obsidian-livesync
|
||||
cat <<EOF >/opt/couchdb/etc/local.d/obsidian-livesync.ini
|
||||
[couchdb]
|
||||
single_node = true
|
||||
max_document_size = 50000000
|
||||
|
||||
[admins]
|
||||
admin = ${COUCHDB_PASSWORD}
|
||||
|
||||
[chttpd]
|
||||
bind_address = 0.0.0.0
|
||||
port = 5984
|
||||
max_http_request_size = 4294967296
|
||||
|
||||
[chttpd_auth]
|
||||
require_valid_user = true
|
||||
|
||||
[httpd]
|
||||
enable_cors = true
|
||||
WWW-Authenticate = Basic realm="couchdb"
|
||||
|
||||
[cors]
|
||||
credentials = true
|
||||
origins = app://obsidian.md,capacitor://localhost,http://localhost
|
||||
headers = accept, authorization, content-type, origin, referer
|
||||
methods = GET, PUT, POST, HEAD, DELETE
|
||||
max_age = 3600
|
||||
EOF
|
||||
cat <<EOF >/opt/obsidian-livesync/.env
|
||||
COUCHDB_URL=http://${LOCAL_IP}:5984
|
||||
COUCHDB_USER=admin
|
||||
COUCHDB_PASSWORD=${COUCHDB_PASSWORD}
|
||||
COUCHDB_DATABASE=obsidiannotes
|
||||
EOF
|
||||
chmod 600 /opt/obsidian-livesync/.env
|
||||
msg_ok "Configured CouchDB"
|
||||
|
||||
msg_info "Creating LiveSync Database"
|
||||
systemctl enable -q couchdb
|
||||
systemctl restart couchdb
|
||||
for _ in {1..30}; do
|
||||
curl -fsS -u "admin:${COUCHDB_PASSWORD}" -X PUT http://127.0.0.1:5984/obsidiannotes >/dev/null 2>&1 && break
|
||||
sleep 1
|
||||
done
|
||||
msg_ok "Created LiveSync Database"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -13,7 +13,7 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
NODE_VERSION="26" setup_nodejs
|
||||
|
||||
msg_info "Installing OmniRoute"
|
||||
$STD npm install -g omniroute@latest
|
||||
|
||||
@@ -64,7 +64,7 @@ $STD sudo -u cool coolconfig set-admin-password --user=admin --password="$COOLPA
|
||||
echo "$COOLPASS" >~/.coolpass
|
||||
msg_ok "Installed Collabora Online"
|
||||
|
||||
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.3.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
|
||||
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.4.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
|
||||
mv /usr/bin/OpenCloud /usr/bin/opencloud
|
||||
|
||||
msg_info "Configuring OpenCloud"
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -26,7 +26,7 @@ create_self_signed_cert
|
||||
|
||||
setup_deb822_repo \
|
||||
"passbolt" \
|
||||
"https://keys.openpgp.org/pks/lookup?op=get&options=mr&search=0x3D1A0346C8E1802F774AEF21DE8B853FC155581D" \
|
||||
"https://download.passbolt.com/pub.key" \
|
||||
"https://download.passbolt.com/ce/debian" \
|
||||
"buster" \
|
||||
"stable"
|
||||
|
||||
@@ -22,12 +22,13 @@ $STD apt install -y \
|
||||
pkg-config
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
RUBY_VERSION="4.0.5" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
NODE_VERSION="22" NODE_MODULE="yarn" setup_nodejs
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
|
||||
|
||||
fetch_and_deploy_gh_release "passwordpusher" "pglombardo/PasswordPusher" "tarball"
|
||||
|
||||
RUBY_VERSION="$(cat /opt/passwordpusher/.ruby-version)" RUBY_INSTALL_RAILS="false" setup_ruby
|
||||
export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
|
||||
|
||||
msg_info "Installing Gem Dependencies"
|
||||
cd /opt/passwordpusher
|
||||
$STD bundle config set --local without 'development test'
|
||||
|
||||
@@ -29,7 +29,7 @@ Pin: version ${RELEASE}
|
||||
Pin-Priority: 1001
|
||||
EOF
|
||||
$STD apt install -y salt-master
|
||||
echo "${RELEASE}" >/~.salt
|
||||
echo "${RELEASE}" >~/.salt
|
||||
msg_ok "Installed Salt"
|
||||
|
||||
motd_ssh
|
||||
|
||||
@@ -125,7 +125,7 @@ EOF
|
||||
|
||||
cat <<EOF >/opt/termix/.env
|
||||
NODE_ENV=production
|
||||
DATA_DIR=/opt/termix/data
|
||||
DATA_DIR=/opt/termix/db/data
|
||||
GUACD_HOST=127.0.0.1
|
||||
GUACD_PORT=4822
|
||||
EOF
|
||||
|
||||
@@ -13,8 +13,7 @@ setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
RELEASE="v2.3.0"
|
||||
fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary" "${RELEASE}" "" "vikunja-*-$(arch_resolve "x86_64" "aarch64").deb"
|
||||
fetch_and_deploy_gh_release "vikunja" "go-vikunja/vikunja" "binary" "latest" "" "vikunja-*-$(arch_resolve "x86_64" "aarch64").deb"
|
||||
|
||||
msg_info "Setting up Vikunja"
|
||||
sed -i 's|^# \(service:\)|\1|' /etc/vikunja/config.yml
|
||||
|
||||
@@ -18,7 +18,7 @@ $STD apt install -y gcc
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
setup_go
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
fetch_and_deploy_gh_release "watcharr" "sbondCo/Watcharr" "tarball"
|
||||
|
||||
msg_info "Setup Watcharr"
|
||||
|
||||
+16
-12
@@ -922,8 +922,10 @@ choose_and_set_storage_for_file() {
|
||||
_list_os_versions() {
|
||||
local ostype="${1:-}"
|
||||
[[ -n "$ostype" ]] || return 0
|
||||
local arch
|
||||
arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)"
|
||||
pveam available -section system 2>/dev/null |
|
||||
grep -E '\.(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
|
||||
@@ -936,8 +938,10 @@ _list_os_versions() {
|
||||
_list_templates() {
|
||||
local search="${1:-}" pattern="${2:-}"
|
||||
[[ -n "$search" ]] || return 0
|
||||
local arch
|
||||
arch="$(dpkg --print-architecture 2>/dev/null || echo amd64)"
|
||||
pveam available -section system 2>/dev/null |
|
||||
grep -E '\.(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
|
||||
@@ -5200,15 +5204,11 @@ EOF
|
||||
# TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop)
|
||||
trap '' TSTP TTIN TTOU
|
||||
|
||||
# lxc-attach takes the controlling terminal while the install runs and does
|
||||
# not hand it back, leaving us in a background process group. Reading from
|
||||
# the terminal then returns EIO instead of blocking, because SIGTTIN is
|
||||
# ignored above - so every recovery prompt fails before the user can answer.
|
||||
# Redirecting to /dev/tty does not help: the rule applies to the terminal,
|
||||
# not the file descriptor. Claim the foreground group back; SIGTTOU is
|
||||
# ignored too, so tcsetpgrp() succeeds instead of stopping us. No-op when we
|
||||
# already are in the foreground. perl is a hard dependency of Proxmox VE.
|
||||
perl -e 'use POSIX; open(my $t, "+<", "/dev/tty") or exit 1; POSIX::tcsetpgrp(fileno($t), getpgrp()) or exit 1;' 2>/dev/null || true
|
||||
# lxc-attach left us in a background process group - claim the terminal back
|
||||
# before we print anything. Note this does NOT hold: the log collection
|
||||
# below uses pct pull/exec, which take it away again, so every interactive
|
||||
# prompt has to reclaim it again right before its read.
|
||||
reclaim_tty
|
||||
|
||||
msg_error "Installation failed in container ${CTID} (exit code: ${install_exit_code})"
|
||||
|
||||
@@ -5338,6 +5338,7 @@ EOF
|
||||
pct enter "$CTID"
|
||||
echo ""
|
||||
echo -en "${YW}Container ${CTID} still running. Remove now? (y/N): ${CL}"
|
||||
reclaim_tty
|
||||
if read -r response </dev/tty && [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
pct stop "$CTID" &>/dev/null || true
|
||||
pct destroy "$CTID" &>/dev/null || true
|
||||
@@ -5497,6 +5498,7 @@ EOF
|
||||
|
||||
local response=""
|
||||
local read_rc
|
||||
reclaim_tty
|
||||
read -t 60 -r response </dev/tty
|
||||
read_rc=$?
|
||||
if [[ $read_rc -eq 0 ]]; then
|
||||
@@ -5761,6 +5763,7 @@ destroy_lxc() {
|
||||
trap 'echo; msg_error "Aborted by user (SIGINT/SIGQUIT)"; return 130' INT QUIT
|
||||
|
||||
local prompt
|
||||
reclaim_tty
|
||||
if ! read -rp "Remove this Container? <y/N> " prompt </dev/tty; then
|
||||
# read returns non-zero on Ctrl-D/ESC
|
||||
msg_error "Aborted input (Ctrl-D/ESC)"
|
||||
@@ -6722,7 +6725,8 @@ create_lxc_container() {
|
||||
# Step 1: Check local templates first (instant)
|
||||
mapfile -t LOCAL_TEMPLATES < <(
|
||||
pveam list "$TEMPLATE_STORAGE" 2>/dev/null |
|
||||
awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" '$1 ~ search && $1 ~ pattern {print $1}' |
|
||||
awk -v search="${TEMPLATE_SEARCH}" -v pattern="${TEMPLATE_PATTERN}" -v arch="${ARCH}" \
|
||||
'$1 ~ search && $1 ~ pattern && $1 ~ ("_" arch "\\.(tar\\.zst|tar\\.xz|tar\\.gz)$") {print $1}' |
|
||||
sed 's|.*/||' | sort -t - -k 2 -V
|
||||
)
|
||||
|
||||
|
||||
+103
@@ -299,6 +299,72 @@ root_check() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# on_pve_host()
|
||||
#
|
||||
# - Returns 0 when executed on a Proxmox VE node, 1 otherwise
|
||||
# - Cheap probe used by the guards below; never exits on its own
|
||||
# ------------------------------------------------------------------------------
|
||||
on_pve_host() {
|
||||
command -v pveversion &>/dev/null
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# require_pve_host()
|
||||
#
|
||||
# - Guard for tools that drive the node itself (pct/pveam/pvesm/pvesh/qm)
|
||||
# - Aborts when not on a PVE node, then validates the PVE version
|
||||
# ------------------------------------------------------------------------------
|
||||
require_pve_host() {
|
||||
if ! on_pve_host; then
|
||||
msg_error "${APP:-This script} must be run on the Proxmox VE host."
|
||||
msg_error "Proxmox tooling (pct/pveam/pvesm/qm) is not available here."
|
||||
exit 232
|
||||
fi
|
||||
pve_check
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# confirm_not_pve_host()
|
||||
#
|
||||
# - Guard for tools that belong inside an LXC/VM but would technically run
|
||||
# on the node as well
|
||||
# - Warns and asks for confirmation instead of hard-failing
|
||||
# ------------------------------------------------------------------------------
|
||||
confirm_not_pve_host() {
|
||||
on_pve_host || return 0
|
||||
|
||||
msg_error "Running on the Proxmox VE host is NOT recommended!"
|
||||
msg_error "${APP:-This script} is meant to be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB:- }Continue anyway? (y/N): "
|
||||
local confirm
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on the Proxmox VE host at your own risk!"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# require_debian_like()
|
||||
#
|
||||
# - Guard for addons that have no Alpine code path
|
||||
# - Aborts early instead of failing halfway through with apt/systemd errors
|
||||
# ------------------------------------------------------------------------------
|
||||
require_debian_like() {
|
||||
if is_alpine; then
|
||||
msg_error "${APP:-This script} does not support Alpine Linux."
|
||||
msg_error "Please use a Debian or Ubuntu based LXC container."
|
||||
exit 238
|
||||
fi
|
||||
if ! command -v apt-get &>/dev/null; then
|
||||
msg_error "${APP:-This script} requires a Debian or Ubuntu based system."
|
||||
exit 238
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# pve_check()
|
||||
#
|
||||
@@ -308,6 +374,10 @@ root_check() {
|
||||
# ------------------------------------------------------------------------------
|
||||
pve_check() {
|
||||
local PVE_VER
|
||||
if ! on_pve_host; then
|
||||
msg_error "${APP:-This script} must be run on the Proxmox VE host."
|
||||
exit 232
|
||||
fi
|
||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||
|
||||
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||
@@ -972,6 +1042,39 @@ ensure_tput() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# reclaim_tty()
|
||||
#
|
||||
# - Reclaims the controlling terminal's foreground process group
|
||||
# - lxc-attach takes the terminal and does not hand it back, leaving us in a
|
||||
# background process group. Reading from the terminal then returns EIO
|
||||
# instead of blocking, because SIGTTIN is ignored during recovery - so the
|
||||
# prompt fails before the user can answer and their keystroke leaks into the
|
||||
# parent shell. Redirecting to /dev/tty does not help: the rule applies to
|
||||
# the terminal, not to the file descriptor.
|
||||
# - pct exec/pull/enter use lxc-attach internally, so the terminal can be taken
|
||||
# away again at any point. Call this immediately before each interactive
|
||||
# read, not once after the install.
|
||||
# - SIGTTOU is ignored inside perl so tcsetpgrp() succeeds instead of stopping
|
||||
# us. No-op when we already are in the foreground or there is no terminal.
|
||||
# perl is a hard dependency of Proxmox VE.
|
||||
# ------------------------------------------------------------------------------
|
||||
reclaim_tty() {
|
||||
command -v perl >/dev/null 2>&1 || return 0
|
||||
[[ -e /dev/tty ]] || return 0
|
||||
|
||||
local pgid
|
||||
pgid=$(ps -o pgid= -p $$ 2>/dev/null | tr -d ' ') || true
|
||||
|
||||
perl -e '
|
||||
use POSIX;
|
||||
$SIG{TTOU} = "IGNORE";
|
||||
my $pgid = $ARGV[0] || POSIX::getpgrp();
|
||||
open(my $t, "+<", "/dev/tty") or exit 1;
|
||||
POSIX::tcsetpgrp(fileno($t), $pgid) or exit 1;
|
||||
' "${pgid:-0}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# is_alpine()
|
||||
#
|
||||
|
||||
@@ -499,6 +499,7 @@ error_handler() {
|
||||
|
||||
local response=""
|
||||
local read_rc
|
||||
declare -f reclaim_tty >/dev/null 2>&1 && reclaim_tty
|
||||
read -t 60 -r response </dev/tty
|
||||
read_rc=$?
|
||||
if [[ $read_rc -eq 0 ]]; then
|
||||
|
||||
+104
-78
@@ -1292,14 +1292,17 @@ create_temp_dir() {
|
||||
# - Copies each given file/directory into a persistent store at
|
||||
# /opt/<NSAPP>.backup, mirroring its absolute path inside the store, and
|
||||
# records it in a manifest so restore_backup needs no arguments.
|
||||
# - Idempotent: if a store from a previous (failed) run already exists, it is
|
||||
# left untouched and no new backup is taken. This keeps the last-known-good
|
||||
# data instead of overwriting it with now-partially-updated data on retry.
|
||||
# - Idempotent per path: a path already recorded in the manifest (from this
|
||||
# run or a previous failed one) is left untouched, keeping the
|
||||
# last-known-good copy instead of overwriting it with now-partially-updated
|
||||
# data on retry. Any requested path NOT yet in the manifest is backed up
|
||||
# now and appended - so a manifest left incomplete by an interrupted prior
|
||||
# run gets completed instead of silently missing paths on restore.
|
||||
# - Missing source paths are skipped with a warning (not fatal).
|
||||
# - Aborts the update on copy failure: if any file/dir cannot be backed up,
|
||||
# the half-written store is removed and the script exits, so the update
|
||||
# never runs against unprotected data (and a retry re-attempts a clean
|
||||
# backup rather than skipping it).
|
||||
# the script exits before the update runs against unprotected data (the
|
||||
# paths already recorded are left in place, so a retry only redoes the one
|
||||
# that failed).
|
||||
#
|
||||
# restore_backup
|
||||
# - Copies every path recorded in the manifest back to its origin (replacing
|
||||
@@ -1318,19 +1321,17 @@ create_backup() {
|
||||
return 0
|
||||
}
|
||||
|
||||
if [[ -f "$manifest" ]]; then
|
||||
msg_ok "Existing backup found at ${store}, skipping backup"
|
||||
return 0
|
||||
if ! mkdir -p "$store" || ! touch "$manifest"; then
|
||||
msg_error "Backup failed: could not create store at ${store} - aborting update"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg_info "Backing up data"
|
||||
if ! mkdir -p "$store" || ! : >"$manifest"; then
|
||||
msg_error "Backup failed: could not create store at ${store} - aborting update"
|
||||
rm -rf "$store"
|
||||
exit 1
|
||||
fi
|
||||
for path in "$@"; do
|
||||
path="${path%/}"
|
||||
if grep -qxF "$path" "$manifest" 2>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
if [[ ! -e "$path" ]]; then
|
||||
msg_warn "Skipping backup of '${path}' (not found)"
|
||||
continue
|
||||
@@ -1338,7 +1339,6 @@ create_backup() {
|
||||
dest="${store}/files${path}"
|
||||
if ! mkdir -p "$(dirname "$dest")" || ! cp -a "$path" "$dest"; then
|
||||
msg_error "Backup of '${path}' failed - aborting update"
|
||||
rm -rf "$store"
|
||||
exit 1
|
||||
fi
|
||||
echo "$path" >>"$manifest"
|
||||
@@ -2040,8 +2040,9 @@ cleanup_orphaned_sources() {
|
||||
local basename_file
|
||||
basename_file=$(basename "$sources_file")
|
||||
|
||||
# NEVER remove debian.sources - this is the standard Debian repository
|
||||
if [[ "$basename_file" == "debian.sources" ]]; then
|
||||
# NEVER remove the distro's own base sources file (debian.sources,
|
||||
# ubuntu.sources, ...)
|
||||
if [[ "$basename_file" == "$(get_os_info id).sources" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
@@ -2113,7 +2114,7 @@ ensure_apt_working() {
|
||||
# Step 4: More aggressive - remove all third-party sources
|
||||
msg_warn "APT update still failing, removing third-party sources"
|
||||
find /etc/apt/sources.list.d/ -type f \( -name "*.sources" -o -name "*.list" \) \
|
||||
! -name "debian.sources" -delete 2>/dev/null || true
|
||||
! -name "$(get_os_info id).sources" -delete 2>/dev/null || true
|
||||
|
||||
# Final attempt
|
||||
if ! $STD apt update; then
|
||||
@@ -2575,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" || {
|
||||
@@ -2606,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
|
||||
}
|
||||
|
||||
@@ -4627,6 +4629,53 @@ _docker_is_noninteractive() {
|
||||
[[ "${DOCKER_NONINTERACTIVE:-}" == "1" || "${DOCKER_NONINTERACTIVE:-}" == "true" || "${DOCKER_NONINTERACTIVE:-}" == "TRUE" ]] || [[ ! -t 0 ]]
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ensure_docker()
|
||||
#
|
||||
# - Docker precondition for addon scripts that ship a compose stack
|
||||
# - Reuses an existing installation, otherwise offers to install Docker
|
||||
# (Debian/Ubuntu via setup_docker, Alpine via apk)
|
||||
# - Aborts when the user declines or Compose is unavailable afterwards
|
||||
# ------------------------------------------------------------------------------
|
||||
ensure_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
return 0
|
||||
fi
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 237
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB:- }Install Docker now? (y/N): "
|
||||
local install_docker_prompt
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP:-this script}. Exiting."
|
||||
exit 254
|
||||
fi
|
||||
|
||||
if is_alpine; then
|
||||
msg_info "Installing Docker"
|
||||
$STD apk add --no-cache docker docker-cli-compose
|
||||
$STD rc-update add docker default
|
||||
$STD rc-service docker start
|
||||
msg_ok "Installed Docker"
|
||||
else
|
||||
setup_docker || {
|
||||
msg_error "Docker installation failed."
|
||||
exit 237
|
||||
}
|
||||
fi
|
||||
|
||||
if ! command -v docker &>/dev/null || ! docker compose version &>/dev/null; then
|
||||
msg_error "Docker or the Compose plugin is still unavailable after installation."
|
||||
exit 237
|
||||
fi
|
||||
}
|
||||
|
||||
setup_docker() {
|
||||
local docker_installed=false
|
||||
local USE_DOCKER_REPO="${USE_DOCKER_REPO:-true}"
|
||||
@@ -4753,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"
|
||||
|
||||
@@ -4792,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
|
||||
@@ -7684,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)
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -20,6 +25,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "actual-budget
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -31,14 +37,6 @@ INSTALL_PATH="/opt/actual-budget-prometheus-exporter"
|
||||
CONFIG_PATH="/opt/actual-budget-prometheus-exporter.env"
|
||||
SERVICE_PATH="/etc/systemd/system/actual-budget-prometheus-exporter.service"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
@@ -6,39 +6,45 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://netbird.io/ | Github: https://github.com/netbirdio/netbird
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ ____ _ __
|
||||
/ | / /__ / /_/ __ )(_)________/ /
|
||||
/ |/ / _ \/ __/ __ / / ___/ __ /
|
||||
/ /| / __/ /_/ /_/ / / / / /_/ /
|
||||
/_/ |_/\___/\__/_____/_/_/ \__,_/
|
||||
APP="add-netbird-lxc"
|
||||
APP_TYPE="addon"
|
||||
|
||||
EOF
|
||||
}
|
||||
header_info
|
||||
set -e
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
while true; do
|
||||
read -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn
|
||||
read -r -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)? " yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
[Nn]*) exit 0 ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
function msg() {
|
||||
local TEXT="$1"
|
||||
echo -e "$TEXT"
|
||||
}
|
||||
echo -e "Loading container list..."
|
||||
|
||||
NODE=$(hostname)
|
||||
MSG_MAX_LENGTH=0
|
||||
@@ -61,37 +67,51 @@ done
|
||||
|
||||
LXC_STATUS=$(pct status "$CTID" | awk '{print $2}')
|
||||
if [[ "$LXC_STATUS" != "running" ]]; then
|
||||
msg "\e[1;33m The container $CTID is not running. Starting it now...\e[0m"
|
||||
msg_info "Container $CTID is not running. Starting it now..."
|
||||
pct start "$CTID"
|
||||
while [[ "$(pct status "$CTID" | awk '{print $2}')" != "running" ]]; do
|
||||
msg "\e[1;33m Waiting for the container to start...\e[0m"
|
||||
msg_info "Waiting for the container to start..."
|
||||
sleep 2
|
||||
done
|
||||
msg "\e[1;32m Container $CTID is now running.\e[0m"
|
||||
msg_ok "Container $CTID is now running."
|
||||
fi
|
||||
|
||||
DISTRO=$(pct exec "$CTID" -- cat /etc/os-release | grep -w "ID" | cut -d'=' -f2 | tr -d '"')
|
||||
if [[ "$DISTRO" != "debian" && "$DISTRO" != "ubuntu" ]]; then
|
||||
msg "\e[1;31m Error: This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting...\e[0m"
|
||||
msg_error "This script only supports Debian or Ubuntu LXC containers. Detected: $DISTRO. Aborting..."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
CTID_CONFIG_PATH=/etc/pve/lxc/${CTID}.conf
|
||||
cat <<EOF >>$CTID_CONFIG_PATH
|
||||
CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
|
||||
cat <<EOF >>"$CTID_CONFIG_PATH"
|
||||
lxc.cgroup2.devices.allow: c 10:200 rwm
|
||||
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
|
||||
EOF
|
||||
header_info
|
||||
msg "Installing NetBird..."
|
||||
|
||||
msg_info "Installing NetBird"
|
||||
pct exec "$CTID" -- bash -c '
|
||||
set -e
|
||||
if ! command -v curl &>/dev/null; then
|
||||
apt-get update -qq
|
||||
apt-get install -y curl >/dev/null
|
||||
fi
|
||||
apt install -y ca-certificates gpg &>/dev/null
|
||||
curl -fsSL "https://pkgs.netbird.io/debian/public.key" | gpg --dearmor >/usr/share/keyrings/netbird-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/netbird-archive-keyring.gpg] https://pkgs.netbird.io/debian stable main" >/etc/apt/sources.list.d/netbird.list
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y ca-certificates gpg &>/dev/null
|
||||
|
||||
# Reuse the shared repository helper instead of hand-rolling the sources entry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
load_functions
|
||||
|
||||
# Drop the legacy keyring from the pre-deb822 layout
|
||||
rm -f /usr/share/keyrings/netbird-archive-keyring.gpg
|
||||
|
||||
setup_deb822_repo \
|
||||
"netbird" \
|
||||
"https://pkgs.netbird.io/debian/public.key" \
|
||||
"https://pkgs.netbird.io/debian" \
|
||||
"stable" \
|
||||
"main"
|
||||
|
||||
apt-get install -y netbird-ui &>/dev/null
|
||||
if systemctl list-unit-files docker.service &>/dev/null; then
|
||||
mkdir -p /etc/systemd/system/netbird.service.d
|
||||
@@ -103,6 +123,5 @@ OVERRIDE
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
'
|
||||
msg "\e[1;32m ✔ Installed NetBird.\e[0m"
|
||||
sleep 2
|
||||
msg "\e[1;31m Reboot ${CTID} LXC to apply the changes, then run netbird up in the LXC console\e[0m"
|
||||
msg_ok "Installed NetBird."
|
||||
echo -e "${YW}Reboot ${CTID} LXC${CL} to apply the changes, then run 'netbird up' in the LXC console"
|
||||
@@ -5,35 +5,34 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://tailscale.com/ | Github: https://github.com/tailscale/tailscale
|
||||
|
||||
set -Eeuo pipefail
|
||||
trap 'echo -e "\n[ERROR] in line $LINENO: exit code $?"' ERR
|
||||
APP="add-tailscale-lxc"
|
||||
APP_TYPE="addon"
|
||||
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ _ __ __
|
||||
/_ __/___ _(_) /_____________ _/ /__
|
||||
/ / / __ `/ / / ___/ ___/ __ `/ / _ \
|
||||
/ / / /_/ / / (__ ) /__/ /_/ / / __/
|
||||
/_/ \__,_/_/_/____/\___/\__,_/_/\___/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function msg_info() { echo -e " \e[1;36m➤\e[0m $1"; }
|
||||
function msg_ok() { echo -e " \e[1;32m✔\e[0m $1"; }
|
||||
function msg_error() { echo -e " \e[1;31m✖\e[0m $1"; }
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-tailscale-lxc" "addon"
|
||||
|
||||
header_info
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
if ! command -v pveversion &>/dev/null; then
|
||||
msg_error "This script must be run on the Proxmox VE host (not inside an LXC container)"
|
||||
exit 232
|
||||
fi
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
while true; do
|
||||
read -rp "This will add Tailscale to an existing LXC Container ONLY. Proceed (y/n)? " yn
|
||||
@@ -44,7 +43,6 @@ while true; do
|
||||
esac
|
||||
done
|
||||
|
||||
header_info
|
||||
msg_info "Loading container list..."
|
||||
|
||||
NODE=$(hostname)
|
||||
@@ -73,10 +71,9 @@ CTID_CONFIG_PATH="/etc/pve/lxc/${CTID}.conf"
|
||||
grep -q "lxc.cgroup2.devices.allow: c 10:200 rwm" "$CTID_CONFIG_PATH" || echo "lxc.cgroup2.devices.allow: c 10:200 rwm" >>"$CTID_CONFIG_PATH"
|
||||
grep -q "lxc.mount.entry: /dev/net/tun" "$CTID_CONFIG_PATH" || echo "lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >>"$CTID_CONFIG_PATH"
|
||||
|
||||
header_info
|
||||
msg_info "Installing Tailscale in CT $CTID"
|
||||
|
||||
pct exec "$CTID" -- sh -c '
|
||||
pct exec "$CTID" -- bash -c '
|
||||
set -e
|
||||
|
||||
# Detect OS inside container
|
||||
@@ -144,16 +141,21 @@ else
|
||||
apt-get install -y curl >/dev/null
|
||||
fi
|
||||
|
||||
# Ensure keyrings directory exists
|
||||
mkdir -p /usr/share/keyrings
|
||||
# Reuse the shared repository helper instead of hand-rolling the sources entry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
load_functions
|
||||
|
||||
curl -fsSL "https://pkgs.tailscale.com/stable/${ID}/${VERSION_CODENAME}.noarmor.gpg" \
|
||||
| tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
||||
# Drop the legacy keyring from the pre-deb822 layout
|
||||
rm -f /usr/share/keyrings/tailscale-archive-keyring.gpg
|
||||
|
||||
echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/${ID} ${VERSION_CODENAME} main" \
|
||||
>/etc/apt/sources.list.d/tailscale.list
|
||||
setup_deb822_repo \
|
||||
"tailscale" \
|
||||
"https://pkgs.tailscale.com/stable/${ID}/${VERSION_CODENAME}.noarmor.gpg" \
|
||||
"https://pkgs.tailscale.com/stable/${ID}" \
|
||||
"${VERSION_CODENAME}" \
|
||||
"main"
|
||||
|
||||
apt-get update -qq
|
||||
apt-get install -y tailscale >/dev/null
|
||||
|
||||
if [ -f /tmp/resolv.conf.backup ]; then
|
||||
@@ -168,4 +170,4 @@ TAGS="${TAGS:+$TAGS; }tailscale"
|
||||
pct set "$CTID" -tags "$TAGS"
|
||||
|
||||
msg_ok "Tailscale installed on CT $CTID"
|
||||
msg_info "Reboot the container, then run 'tailscale up' inside the container to activate."
|
||||
echo -e "${YW}Reboot the container${CL}, then run 'tailscale up' inside the container to activate."
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
apk -U add curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
@@ -36,28 +37,6 @@ DEFAULT_PORT=8080
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ __ ____ __ _____
|
||||
/ | ____/ /___ ___ ______ __________/ / / / /___ ____ ___ ___ / ___/__ ______ _____
|
||||
/ /| |/ __ / __ `/ / / / __ `/ ___/ __ / /_/ / __ \/ __ `__ \/ _ \ \__ \/ / / / __ \/ ___/
|
||||
/ ___ / /_/ / /_/ / /_/ / /_/ / / / /_/ / __ / /_/ / / / / / / __/ ___/ / /_/ / / / / /__
|
||||
/_/ |_\__,_/\__, /\__,_/\__,_/_/ \__,_/_/ /_/\____/_/ /_/ /_/\___/ /____/\__, /_/ /_/\___/
|
||||
/____/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ==============================================================================
|
||||
get_ip() {
|
||||
hostname -I 2>/dev/null | awk '{print $1}' || ip -4 addr show scope global 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1 || echo "127.0.0.1"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
@@ -114,16 +93,12 @@ function update() {
|
||||
fi
|
||||
msg_ok "Stopped service"
|
||||
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/adguardhome-sync.yaml.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
BACKUP_DIR="/opt/adguardhome-sync_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_amd64.tar.gz"
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
|
||||
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/adguardhome-sync.yaml.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/adguardhome-sync.yaml.bak
|
||||
msg_ok "Restored configuration"
|
||||
restore_backup
|
||||
|
||||
msg_info "Starting service"
|
||||
if [[ "$OS" == "Alpine" ]]; then
|
||||
@@ -141,10 +116,7 @@ function update() {
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
local ip
|
||||
ip=$(get_ip)
|
||||
|
||||
fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_amd64.tar.gz"
|
||||
fetch_and_deploy_gh_release "adguardhome-sync" "bakito/adguardhome-sync" "prebuild" "latest" "$INSTALL_PATH" "adguardhome-sync_*_linux_$(arch_resolve).tar.gz"
|
||||
|
||||
# Gather configuration from user
|
||||
echo ""
|
||||
@@ -153,7 +125,7 @@ function install() {
|
||||
echo ""
|
||||
|
||||
# Origin instance
|
||||
echo -e "${YW}── Origin (Primary) Instance ──${CL}"
|
||||
echo -e "${YW}── Origin (Primary) Instance ──${CL}"
|
||||
local origin_url origin_user origin_pass
|
||||
read -rp " Origin URL (e.g., http://192.168.1.1): " origin_url
|
||||
origin_url="${origin_url:-http://192.168.1.1}"
|
||||
@@ -167,7 +139,7 @@ function install() {
|
||||
|
||||
# Replica instance
|
||||
echo ""
|
||||
echo -e "${YW}── Replica Instance ──${CL}"
|
||||
echo -e "${YW}── Replica Instance ──${CL}"
|
||||
local replica_url replica_user replica_pass
|
||||
read -rp " Replica URL (e.g., http://192.168.1.2): " replica_url
|
||||
replica_url="${replica_url:-http://192.168.1.2}"
|
||||
@@ -293,7 +265,7 @@ UPDATEEOF
|
||||
|
||||
echo ""
|
||||
msg_ok "${APP} installed successfully"
|
||||
msg_ok "Web UI: ${BL}http://${ip}:${DEFAULT_PORT}${CL}"
|
||||
msg_ok "Web UI: ${BL}http://${IP}:${DEFAULT_PORT}${CL}"
|
||||
msg_ok "Config: ${BL}${CONFIG_PATH}${CL}"
|
||||
echo ""
|
||||
msg_warn "Edit the config file to add your AdGuardHome instances!"
|
||||
@@ -319,7 +291,8 @@ fi
|
||||
|
||||
header_info
|
||||
|
||||
IP=$(get_ip)
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# Check if already installed
|
||||
if [[ -d "$INSTALL_PATH" && -f "$INSTALL_PATH/adguardhome-sync" ]]; then
|
||||
|
||||
@@ -1,52 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ ____ ______ __ __
|
||||
/ _ | / / / /_ __/__ __ _ ___ / /__ _/ /____ ___
|
||||
/ __ |/ / / / / / -_) ' \/ _ \/ / _ `/ __/ -_|_-<
|
||||
/_/ |_/_/_/ /_/ \__/_/_/_/ .__/_/\_,_/\__/\__/___/
|
||||
/_/
|
||||
EOF
|
||||
}
|
||||
APP="all-templates"
|
||||
APP_TYPE="addon"
|
||||
|
||||
set -eEuo pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local DEFAULT='Unknown failure occured.'
|
||||
local REASON="\e[97m${1:-$DEFAULT}\e[39m"
|
||||
local FLAG="\e[91m[ERROR] \e[93m$EXIT@$LINE"
|
||||
msg "$FLAG $REASON" 1>&2
|
||||
[ ! -z ${CTID-} ] && cleanup_ctid
|
||||
exit $EXIT
|
||||
}
|
||||
function warn() {
|
||||
local REASON="\e[97m$1\e[39m"
|
||||
local FLAG="\e[93m[WARNING]\e[39m"
|
||||
msg "$FLAG $REASON"
|
||||
}
|
||||
function info() {
|
||||
local REASON="$1"
|
||||
local FLAG="\e[36m[INFO]\e[39m"
|
||||
msg "$FLAG $REASON"
|
||||
}
|
||||
function msg() {
|
||||
local TEXT="$1"
|
||||
echo -e "$TEXT"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "addon"
|
||||
|
||||
# Enable error handling; destroy any partially-created container before reporting the error
|
||||
set -Eeuo pipefail
|
||||
function _cleanup_on_error() {
|
||||
local ec=$? cmd="$BASH_COMMAND"
|
||||
[[ -n "${CTID:-}" ]] && cleanup_ctid
|
||||
error_handler "$ec" "$cmd"
|
||||
}
|
||||
trap '_cleanup_on_error' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
function validate_container_id() {
|
||||
local ctid="$1"
|
||||
# Check if ID is numeric
|
||||
@@ -79,12 +67,14 @@ function cleanup_ctid() {
|
||||
fi
|
||||
}
|
||||
|
||||
header_info
|
||||
require_pve_host
|
||||
|
||||
# Stop Proxmox VE Monitor-All if running
|
||||
if systemctl is-active -q ping-instances.service; then
|
||||
systemctl stop ping-instances.service
|
||||
fi
|
||||
header_info
|
||||
echo "Loading..."
|
||||
msg_info "Loading"
|
||||
pveam update >/dev/null 2>&1
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Templates" --yesno "This will allow for the creation of one of the many Template LXC Containers. Proceed?" 10 68
|
||||
TEMPLATE_MENU=()
|
||||
@@ -97,8 +87,8 @@ done < <(pveam available)
|
||||
TEMPLATE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "All Template LXCs" --radiolist "\nSelect a Template LXC to create:\n" 16 $((MSG_MAX_LENGTH + 58)) 10 "${TEMPLATE_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
|
||||
[ -z "$TEMPLATE" ] && {
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Template LXC Selected" --msgbox "It appears that no Template LXC container was selected" 10 68
|
||||
msg "Done"
|
||||
exit
|
||||
echo "Done"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Setup script environment
|
||||
@@ -108,9 +98,9 @@ PASS="$(openssl rand -base64 8)"
|
||||
# Get valid Container ID
|
||||
CTID=$(pvesh get /cluster/nextid)
|
||||
if ! validate_container_id "$CTID"; then
|
||||
warn "Container ID $CTID is already in use."
|
||||
msg_warn "Container ID $CTID is already in use."
|
||||
CTID=$(get_valid_container_id "$CTID")
|
||||
info "Using next available ID: $CTID"
|
||||
msg_info "Using next available ID: $CTID"
|
||||
fi
|
||||
|
||||
PCT_OPTIONS="
|
||||
@@ -142,7 +132,10 @@ function select_storage() {
|
||||
CONTENT='vztmpl'
|
||||
CONTENT_LABEL='Container template'
|
||||
;;
|
||||
*) false || die "Invalid storage class." ;;
|
||||
*)
|
||||
msg_error "Invalid storage class."
|
||||
exit 112
|
||||
;;
|
||||
esac
|
||||
|
||||
# Query all storage locations
|
||||
@@ -161,8 +154,9 @@ function select_storage() {
|
||||
|
||||
# Select storage location
|
||||
if [ $((${#MENU[@]} / 3)) -eq 0 ]; then
|
||||
warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
|
||||
die "Unable to detect valid storage location."
|
||||
msg_warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
|
||||
msg_error "Unable to detect valid storage location."
|
||||
if [[ "$CONTENT" == "rootdir" ]]; then exit 119; else exit 120; fi
|
||||
elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
||||
printf ${MENU[0]}
|
||||
else
|
||||
@@ -171,43 +165,54 @@ function select_storage() {
|
||||
STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
|
||||
"Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\n\n" \
|
||||
16 $(($MSG_MAX_LENGTH + 23)) 6 \
|
||||
"${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
|
||||
"${MENU[@]}" 3>&1 1>&2 2>&3) || {
|
||||
msg_error "Menu aborted."
|
||||
exit 254
|
||||
}
|
||||
done
|
||||
printf $STORAGE
|
||||
fi
|
||||
}
|
||||
header_info
|
||||
|
||||
# Get template storage
|
||||
TEMPLATE_STORAGE=$(select_storage template)
|
||||
info "Using '$TEMPLATE_STORAGE' for template storage."
|
||||
msg_info "Using '$TEMPLATE_STORAGE' for template storage."
|
||||
|
||||
# Get container storage
|
||||
CONTAINER_STORAGE=$(select_storage container)
|
||||
info "Using '$CONTAINER_STORAGE' for container storage."
|
||||
msg_info "Using '$CONTAINER_STORAGE' for container storage."
|
||||
|
||||
# Download template
|
||||
msg "Downloading LXC template (Patience)..."
|
||||
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || die "A problem occured while downloading the LXC template."
|
||||
msg_info "Downloading LXC template (Patience)"
|
||||
pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null || {
|
||||
msg_error "A problem occured while downloading the LXC template."
|
||||
exit 222
|
||||
}
|
||||
msg_ok "Downloaded LXC template"
|
||||
|
||||
# Create variable for 'pct' options
|
||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
|
||||
[[ " ${PCT_OPTIONS[*]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
|
||||
|
||||
# Create LXC
|
||||
msg "Creating LXC container..."
|
||||
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null ||
|
||||
die "A problem occured while trying to create container."
|
||||
msg_info "Creating LXC container"
|
||||
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} "${PCT_OPTIONS[@]}" >/dev/null || {
|
||||
msg_error "A problem occured while trying to create container."
|
||||
exit 209
|
||||
}
|
||||
msg_ok "Created LXC container"
|
||||
|
||||
# Save password
|
||||
echo "$NAME password: ${PASS}" >>~/$NAME.creds # file is located in the Proxmox root directory
|
||||
|
||||
# Start container
|
||||
msg "Starting LXC Container..."
|
||||
msg_info "Starting LXC Container"
|
||||
pct start "$CTID"
|
||||
sleep 5
|
||||
msg_ok "Started LXC Container"
|
||||
|
||||
# Get container IP
|
||||
set +eEuo pipefail
|
||||
set +Eeuo pipefail
|
||||
max_attempts=5
|
||||
attempt=1
|
||||
IP=""
|
||||
@@ -216,30 +221,29 @@ while [[ $attempt -le $max_attempts ]]; do
|
||||
if [[ -n $IP ]]; then
|
||||
break
|
||||
else
|
||||
warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
|
||||
msg_warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
|
||||
sleep 5
|
||||
((attempt++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z $IP ]]; then
|
||||
warn "Maximum number of attempts reached. IP address not found."
|
||||
msg_warn "Maximum number of attempts reached. IP address not found."
|
||||
IP="NOT FOUND"
|
||||
fi
|
||||
|
||||
set -eEuo pipefail
|
||||
set -Eeuo pipefail
|
||||
# Start Proxmox VE Monitor-All if available
|
||||
if [[ -f /etc/systemd/system/ping-instances.service ]]; then
|
||||
systemctl start ping-instances.service
|
||||
fi
|
||||
|
||||
# Success message
|
||||
header_info
|
||||
echo
|
||||
info "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
|
||||
msg_ok "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
|
||||
echo
|
||||
info "Proceed to the LXC console to complete the setup."
|
||||
echo -e "${YW}Proceed to the LXC console to complete the setup.${CL}"
|
||||
echo
|
||||
info "login: root"
|
||||
info "password: $PASS"
|
||||
echo -e "${YW}login: root${CL}"
|
||||
echo -e "${YW}password: $PASS${CL}"
|
||||
echo
|
||||
+9
-33
@@ -6,8 +6,13 @@
|
||||
# Source: https://github.com/getarcaneapp/arcane
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -32,21 +37,6 @@ DEFAULT_PORT=3552
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
___ ____ _________ _ ________
|
||||
/ | / __ \/ ____/ | / | / / ____/
|
||||
/ /| | / /_/ / / / /| | / |/ / __/
|
||||
/ ___ |/ _, _/ /___/ ___ |/ /| / /___
|
||||
/_/ |_/_/ |_|\____/_/ |_/_/ |_/_____/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -82,26 +72,11 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK DOCKER
|
||||
# ==============================================================================
|
||||
function check_docker() {
|
||||
if ! command -v docker &>/dev/null; then
|
||||
msg_error "Docker is not installed. This script requires an existing Docker LXC. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
if ! docker compose version &>/dev/null; then
|
||||
msg_error "Docker Compose plugin is not available. Please install it before running this script. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') and Docker Compose are available"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_docker
|
||||
ensure_docker
|
||||
|
||||
msg_info "Creating install directory"
|
||||
mkdir -p "$INSTALL_PATH"
|
||||
@@ -178,6 +153,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -5,62 +5,153 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://coder.com/ | Github: https://github.com/coder/code-server
|
||||
|
||||
function header_info {
|
||||
cat <<"EOF"
|
||||
______ __ _____
|
||||
/ ____/___ ____/ /__ / ___/___ ______ _____ _____
|
||||
/ / / __ \/ __ / _ \ \__ \/ _ \/ ___/ | / / _ \/ ___/
|
||||
/ /___/ /_/ / /_/ / __/ ___/ / __/ / | |/ / __/ /
|
||||
\____/\____/\__,_/\___/ /____/\___/_/ |___/\___/_/
|
||||
|
||||
EOF
|
||||
}
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="Coder Code Server"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "coder-code-server" "addon"
|
||||
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
APP="Coder Code Server"
|
||||
APP_TYPE="addon"
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local reason="Unknown failure occured."
|
||||
local msg="${1:-$reason}"
|
||||
local flag="${RD}‼ ERROR ${CL}$EXIT@$LINE"
|
||||
echo -e "$flag $msg" 1>&2
|
||||
exit "$EXIT"
|
||||
}
|
||||
clear
|
||||
header_info
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Install on Proxmox "
|
||||
exit
|
||||
ensure_usr_local_bin_persist
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
confirm_not_pve_host
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl disable --now code-server@"$USER" &>/dev/null || true
|
||||
$STD apt remove -y code-server
|
||||
rm -f "$HOME/.coder-code-server"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
if check_for_gh_release "coder-code-server" "coder/code-server"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "coder-code-server" "coder/code-server" "binary" "latest" "/opt/coder-code-server" "code-server_*_$(arch_resolve).deb"
|
||||
systemctl restart code-server@"$USER"
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
curl \
|
||||
git
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
config_path="${HOME}/.config/code-server/config.yaml"
|
||||
preexisting_config=false
|
||||
if [ -f "$config_path" ]; then
|
||||
preexisting_config=true
|
||||
fi
|
||||
|
||||
fetch_and_deploy_gh_release "coder-code-server" "coder/code-server" "binary" "latest" "/opt/coder-code-server" "code-server_*_$(arch_resolve).deb"
|
||||
mkdir -p "${HOME}/.config/code-server/"
|
||||
|
||||
if [ "$preexisting_config" = false ]; then
|
||||
cat <<EOF >"$config_path"
|
||||
bind-addr: 0.0.0.0:8680
|
||||
auth: none
|
||||
password:
|
||||
cert: false
|
||||
EOF
|
||||
fi
|
||||
systemctl enable -q --now code-server@"$USER"
|
||||
systemctl restart code-server@"$USER"
|
||||
if ! systemctl is-active --quiet code-server@"$USER"; then
|
||||
msg_error "code-server service failed to start."
|
||||
exit 150
|
||||
fi
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating update script"
|
||||
ensure_usr_local_bin_persist
|
||||
cat <<'EOF' >/usr/local/bin/update_coder-code-server
|
||||
#!/usr/bin/env bash
|
||||
# Coder Code Server Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/coder-code-server.sh)"
|
||||
EOF
|
||||
chmod +x /usr/local/bin/update_coder-code-server
|
||||
msg_ok "Created update script (/usr/local/bin/update_coder-code-server)"
|
||||
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://${IP}:8680${CL} \n"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
if command -v code-server &>/dev/null; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 233
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
if [ -e /etc/alpine-release ]; then
|
||||
echo -e "⚠️ Can't Install on Alpine"
|
||||
exit
|
||||
|
||||
if [[ -d "$HOME" && -f "$HOME/.coder-code-server" ]] || command -v code-server &>/dev/null; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
uninstall
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_warn "No action selected. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
@@ -68,53 +159,4 @@ while true; do
|
||||
esac
|
||||
done
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y curl &>/dev/null
|
||||
apt-get install -y git &>/dev/null
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
VERSION=$(curl -fsSL https://api.github.com/repos/coder/code-server/releases/latest |
|
||||
grep "tag_name" |
|
||||
awk '{print substr($2, 3, length($2)-4) }')
|
||||
|
||||
msg_info "Installing Code-Server v${VERSION}"
|
||||
config_path="${HOME}/.config/code-server/config.yaml"
|
||||
preexisting_config=false
|
||||
|
||||
if [ -f "$config_path" ]; then
|
||||
preexisting_config=true
|
||||
fi
|
||||
|
||||
curl -fOL https://github.com/coder/code-server/releases/download/v"$VERSION"/code-server_"${VERSION}"_amd64.deb &>/dev/null
|
||||
dpkg -i code-server_"${VERSION}"_amd64.deb &>/dev/null
|
||||
rm -rf code-server_"${VERSION}"_amd64.deb
|
||||
mkdir -p "${HOME}/.config/code-server/"
|
||||
|
||||
if [ "$preexisting_config" = false ]; then
|
||||
cat <<EOF >"$config_path"
|
||||
bind-addr: 0.0.0.0:8680
|
||||
auth: none
|
||||
password:
|
||||
cert: false
|
||||
EOF
|
||||
fi
|
||||
systemctl enable -q --now code-server@"$USER"
|
||||
systemctl restart code-server@"$USER"
|
||||
if ! systemctl is-active --quiet code-server@"$USER"; then
|
||||
error_exit "code-server service failed to start."
|
||||
fi
|
||||
msg_ok "Installed Code-Server v${VERSION} on $hostname"
|
||||
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://$IP:8680${CL} \n"
|
||||
install
|
||||
+2
-57
@@ -66,66 +66,11 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_or_install_docker
|
||||
ensure_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
@@ -172,7 +117,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
check_proxmox_host
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
+18
-20
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -45,28 +50,13 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
SERVICE_PATH="/etc/init.d/copyparty"
|
||||
elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
||||
OS="Debian"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
PKG_MANAGER="apt install -y"
|
||||
SERVICE_PATH="/etc/systemd/system/copyparty.service"
|
||||
else
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ ____ __
|
||||
/ ____/___ ____ __ __/ __ \____ ______/ /___ __
|
||||
/ / / __ \/ __ \/ / / / /_/ / __ `/ ___/ __/ / / /
|
||||
/ /___/ /_/ / /_/ / /_/ / ____/ /_/ / / / /_/ /_/ /
|
||||
\____/\____/ .___/\__, /_/ \__,_/_/ \__/\__, /
|
||||
/_/ /____/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ==============================================================================
|
||||
@@ -173,9 +163,17 @@ function install() {
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
$STD $PKG_MANAGER python3 python3-pil ffmpeg curl
|
||||
$STD $PKG_MANAGER \
|
||||
python3 \
|
||||
python3-pil \
|
||||
ffmpeg \
|
||||
curl
|
||||
else
|
||||
$STD $PKG_MANAGER python3 py3-pillow ffmpeg curl
|
||||
$STD $PKG_MANAGER \
|
||||
python3 \
|
||||
py3-pillow \
|
||||
ffmpeg \
|
||||
curl
|
||||
fi
|
||||
msg_ok "Dependencies installed (with thumbnail support)"
|
||||
|
||||
|
||||
+11
-32
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -20,6 +25,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "cronmaster" "
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -31,29 +37,6 @@ CONFIG_PATH="/opt/cronmaster/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/cronmaster.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ __ ___ __
|
||||
/ ____/________ ____ / |/ /___ ______/ /____ _____
|
||||
/ / / ___/ __ \/ __ \/ /|_/ / __ `/ ___/ __/ _ \/ ___/
|
||||
/ /___/ / / /_/ / / / / / / / /_/ (__ ) /_/ __/ /
|
||||
\____/_/ \____/_/ /_/_/ /_/\__,_/____/\__/\___/_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -77,16 +60,12 @@ function update() {
|
||||
systemctl stop cronmaster.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/cronmaster.env.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
BACKUP_DIR="/opt/cronmaster_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "cronmaster" "fccview/cronmaster" "prebuild" "latest" "$INSTALL_PATH" "cronmaster_*_prebuild.tar.gz"
|
||||
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/cronmaster.env.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/cronmaster.env.bak
|
||||
msg_ok "Restored configuration"
|
||||
restore_backup
|
||||
|
||||
msg_info "Starting service"
|
||||
systemctl start cronmaster
|
||||
|
||||
+35
-63
@@ -5,89 +5,61 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.crowdsec.net/ | Github: https://github.com/crowdsecurity/crowdsec
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="CrowdSec"
|
||||
hostname="$(hostname)"
|
||||
APP_TYPE="addon"
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "crowdsec" "addon"
|
||||
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
shopt -s expand_aliases
|
||||
alias die='EXIT=$? LINE=$LINENO error_exit'
|
||||
trap die ERR
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
|
||||
function error_exit() {
|
||||
trap - ERR
|
||||
local reason="Unknown failure occured."
|
||||
local msg="${1:-$reason}"
|
||||
local flag="${RD}‼ ERROR ${CL}$EXIT@$LINE"
|
||||
echo -e "$flag $msg" 1>&2
|
||||
exit "$EXIT"
|
||||
}
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Install on Proxmox "
|
||||
exit
|
||||
fi
|
||||
while true; do
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
clear
|
||||
function header_info() {
|
||||
echo -e "${BL}
|
||||
_____ _ _____
|
||||
/ ____| | |/ ____|
|
||||
| | _ __ _____ ____| | (___ ___ ___
|
||||
| | | __/ _ \ \ /\ / / _ |\___ \ / _ \/ __|
|
||||
| |____| | | (_) \ V V / (_| |____) | __/ (__
|
||||
\_____|_| \___/ \_/\_/ \__ _|_____/ \___|\___|
|
||||
${CL}"
|
||||
}
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_info "Setting up ${APP} Repository"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y curl &>/dev/null
|
||||
apt-get install -y gnupg &>/dev/null
|
||||
curl -fsSL "https://install.crowdsec.net" | bash &>/dev/null
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
curl \
|
||||
gnupg
|
||||
$STD bash -c "curl -fsSL https://install.crowdsec.net | bash"
|
||||
msg_ok "Setup ${APP} Repository"
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y crowdsec &>/dev/null
|
||||
msg_ok "Installed ${APP} on $hostname"
|
||||
$STD apt update
|
||||
$STD apt install -y crowdsec
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Installing ${APP} Common Bouncer"
|
||||
apt-get install -y crowdsec-firewall-bouncer-iptables &>/dev/null
|
||||
$STD apt install -y crowdsec-firewall-bouncer-iptables
|
||||
msg_ok "Installed ${APP} Common Bouncer"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
+2
-57
@@ -72,66 +72,11 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_or_install_docker
|
||||
ensure_docker
|
||||
|
||||
msg_info "Creating install directories"
|
||||
mkdir -p "$INSTALL_PATH" "$STACKS_PATH"
|
||||
@@ -167,7 +112,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
check_proxmox_host
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
+2
-57
@@ -65,66 +65,11 @@ function update() {
|
||||
exit
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_or_install_docker
|
||||
ensure_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
@@ -170,7 +115,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
check_proxmox_host
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -5,55 +5,51 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/filebrowserspace/quantum
|
||||
|
||||
function header_info() {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_______ __ ____ ____ __
|
||||
/ ____(_) /__ / __ )_________ _ __________ _____ / __ \__ ______ _____ / /___ ______ ___
|
||||
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/ / / / / / / / __ `/ __ \/ __/ / / / __ `__ \
|
||||
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ / / /_/ / /_/ / /_/ / / / / /_/ /_/ / / / / / /
|
||||
/_/ /_/_/\___/_____/_/ \____/|__/|__/____/\___/_/ \___\_\__,_/\__,_/_/ /_/\__/\__,_/_/ /_/ /_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="FileBrowser Quantum"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/usr/local/bin/filebrowser"
|
||||
CONFIG_PATH="/usr/local/community-scripts/fq-config.yaml"
|
||||
DEFAULT_PORT=8080
|
||||
SRC_DIR="/"
|
||||
TMP_BIN="/tmp/filebrowser.$$"
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser-quantum" "addon"
|
||||
|
||||
# Get primary IP
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# Proxmox Host Warning
|
||||
if [[ -d "/etc/pve" ]]; then
|
||||
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}"
|
||||
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}"
|
||||
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}"
|
||||
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}"
|
||||
msg_warn "Running this addon directly on the Proxmox host is not recommended!"
|
||||
msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
|
||||
msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
|
||||
msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
|
||||
echo ""
|
||||
echo -n "Continue anyway on the Proxmox host? (y/N): "
|
||||
echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
|
||||
read -r host_confirm
|
||||
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${YW}Aborted.${CL}"
|
||||
msg_error "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -66,18 +62,12 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
PKG_MANAGER="apt install -y"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}$1...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Detect legacy FileBrowser installation
|
||||
LEGACY_DB="/usr/local/community-scripts/filebrowser.db"
|
||||
LEGACY_BIN="/usr/local/bin/filebrowser"
|
||||
@@ -85,80 +75,82 @@ LEGACY_SERVICE_DEB="/etc/systemd/system/filebrowser.service"
|
||||
LEGACY_SERVICE_ALP="/etc/init.d/filebrowser"
|
||||
|
||||
if [[ -f "$LEGACY_DB" || -f "$LEGACY_BIN" && ! -f "$CONFIG_PATH" ]]; then
|
||||
echo -e "${YW}⚠️ Detected legacy FileBrowser installation.${CL}"
|
||||
echo -n "Uninstall legacy FileBrowser and continue with Quantum install? (y/n): "
|
||||
msg_warn "Detected legacy FileBrowser installation."
|
||||
echo -n "${TAB}Uninstall legacy FileBrowser and continue with Quantum install? (y/n): "
|
||||
read -r remove_legacy
|
||||
if [[ "${remove_legacy,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling legacy FileBrowser"
|
||||
if [[ -f "$LEGACY_SERVICE_DEB" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
rm -f "$LEGACY_SERVICE_DEB"
|
||||
elif [[ -f "$LEGACY_SERVICE_ALP" ]]; then
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rm -f "$LEGACY_SERVICE_ALP"
|
||||
fi
|
||||
rm -f "$LEGACY_BIN" "$LEGACY_DB"
|
||||
msg_ok "Legacy FileBrowser removed"
|
||||
else
|
||||
echo -e "${YW}❌ Installation aborted by user.${CL}"
|
||||
msg_error "Installation aborted by user."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Existing installation
|
||||
if [[ -f "$INSTALL_PATH" ]]; then
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
echo -n "Uninstall ${APP}? (y/N): "
|
||||
msg_warn "${APP} is already installed."
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$CONFIG_PATH"
|
||||
rm -f "$INSTALL_PATH" "$CONFIG_PATH" "$HOME/.filebrowser-quantum"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "Update ${APP}? (y/N): "
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN"
|
||||
chmod +x "$TMP_BIN"
|
||||
mv -f "$TMP_BIN" /usr/local/bin/filebrowser
|
||||
msg_ok "Updated ${APP}"
|
||||
if check_for_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser"; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $STD $PKG_MANAGER curl; fi
|
||||
fetch_and_deploy_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser" "singlefile" "latest" "/usr/local/bin" "linux-$(arch_resolve)-filebrowser"
|
||||
mv -f /usr/local/bin/filebrowser-quantum "$INSTALL_PATH"
|
||||
msg_ok "Updated ${APP}"
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
msg_warn "Update skipped. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${YW}⚠️ ${APP} is not installed.${CL}"
|
||||
echo -n "Enter port number (Default: ${DEFAULT_PORT}): "
|
||||
msg_warn "${APP} is not installed."
|
||||
echo -n "${TAB}Enter port number (Default: ${DEFAULT_PORT}): "
|
||||
read -r PORT
|
||||
PORT=${PORT:-$DEFAULT_PORT}
|
||||
|
||||
echo -n "Install ${APP}? (y/n): "
|
||||
echo -n "${TAB}Install ${APP}? (y/n): "
|
||||
read -r install_prompt
|
||||
if ! [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$PKG_MANAGER curl ffmpeg &>/dev/null
|
||||
curl -fsSL https://github.com/gtsteffaniak/filebrowser/releases/latest/download/linux-amd64-filebrowser -o "$TMP_BIN"
|
||||
chmod +x "$TMP_BIN"
|
||||
mv -f "$TMP_BIN" /usr/local/bin/filebrowser
|
||||
$STD $PKG_MANAGER \
|
||||
curl \
|
||||
ffmpeg
|
||||
fetch_and_deploy_gh_release "filebrowser-quantum" "gtsteffaniak/filebrowser" "singlefile" "latest" "/usr/local/bin" "linux-$(arch_resolve)-filebrowser"
|
||||
mv -f /usr/local/bin/filebrowser-quantum "$INSTALL_PATH"
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Preparing configuration directory"
|
||||
@@ -167,7 +159,7 @@ chown root:root /usr/local/community-scripts
|
||||
chmod 755 /usr/local/community-scripts
|
||||
msg_ok "Directory prepared"
|
||||
|
||||
echo -n "Use No Authentication? (y/N): "
|
||||
echo -n "${TAB}Use No Authentication? (y/N): "
|
||||
read -r noauth_prompt
|
||||
|
||||
# === YAML CONFIG GENERATION ===
|
||||
@@ -251,9 +243,9 @@ depend() {
|
||||
}
|
||||
EOF
|
||||
chmod +x "$SERVICE_PATH"
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
$STD rc-update add filebrowser default
|
||||
$STD rc-service filebrowser start
|
||||
fi
|
||||
|
||||
msg_ok "Service created successfully"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
|
||||
+62
-77
@@ -5,53 +5,50 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://filebrowser.org/ | Github: https://github.com/filebrowser/filebrowser
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_______ __ ____
|
||||
/ ____(_) /__ / __ )_________ _ __________ _____
|
||||
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/
|
||||
/ __/ / / / __/ /_/ / / / /_/ / |/ |/ (__ ) __/ /
|
||||
/_/ /_/_/\___/_____/_/ \____/|__/|__/____/\___/_/
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="FileBrowser"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/usr/local/bin/filebrowser"
|
||||
DB_PATH="/usr/local/community-scripts/filebrowser.db"
|
||||
DEFAULT_PORT=8080
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser" "addon"
|
||||
|
||||
# Get first non-loopback IP & Detect primary network interface dynamically
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# Proxmox Host Warning
|
||||
if [[ -d "/etc/pve" ]]; then
|
||||
echo -e "${RD}⚠️ Warning: Running this addon directly on the Proxmox host is not recommended!${CL}"
|
||||
echo -e "${YW} Only the boot disk will be visible — passthrough drives will not be indexed.${CL}"
|
||||
echo -e "${YW} This causes incorrect disk usage stats and incomplete file browsing.${CL}"
|
||||
echo -e "${YW} Run this addon inside an LXC or VM instead and mount your drives there.${CL}"
|
||||
msg_warn "Running this addon directly on the Proxmox host is not recommended!"
|
||||
msg_warn "Only the boot disk will be visible — passthrough drives will not be indexed."
|
||||
msg_warn "This causes incorrect disk usage stats and incomplete file browsing."
|
||||
msg_warn "Run this addon inside an LXC or VM instead and mount your drives there."
|
||||
echo ""
|
||||
echo -n "Continue anyway on the Proxmox host? (y/N): "
|
||||
echo -n "${TAB}Continue anyway on the Proxmox host? (y/N): "
|
||||
read -r host_confirm
|
||||
if [[ ! "${host_confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${YW}Aborted.${CL}"
|
||||
msg_error "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -64,71 +61,59 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
PKG_MANAGER="apt install -y"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -e "${INFO} ${YW}${msg}...${CL}"
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
if [ -f "$INSTALL_PATH" ]; then
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
msg_warn "${APP} is already installed."
|
||||
read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
systemctl disable --now filebrowser.service &>/dev/null || true
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rc-service filebrowser stop &>/dev/null || true
|
||||
rc-update del filebrowser &>/dev/null || true
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH"
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH" "$HOME/.filebrowser"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to update ${APP}? (y/N): " update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Updated ${APP}"
|
||||
if check_for_gh_release "filebrowser" "filebrowser/filebrowser"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "filebrowser" "filebrowser/filebrowser" "prebuild" "latest" "/opt/filebrowser-dist" "linux-$(arch_resolve)-filebrowser.tar.gz"
|
||||
install -m 755 /opt/filebrowser-dist/filebrowser "$INSTALL_PATH"
|
||||
rm -rf /opt/filebrowser-dist
|
||||
msg_ok "Updated ${APP}"
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
msg_warn "Update skipped. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${YW}⚠️ ${APP} is not installed.${CL}"
|
||||
msg_warn "${APP} is not installed."
|
||||
read -r -p "Enter port number (Default: ${DEFAULT_PORT}): " PORT
|
||||
PORT=${PORT:-$DEFAULT_PORT}
|
||||
|
||||
read -r -p "Would you like to install ${APP}? (y/n): " install_prompt
|
||||
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$PKG_MANAGER wget tar curl &>/dev/null
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
$STD $PKG_MANAGER \
|
||||
tar \
|
||||
curl
|
||||
fetch_and_deploy_gh_release "filebrowser" "filebrowser/filebrowser" "prebuild" "latest" "/opt/filebrowser-dist" "linux-$(arch_resolve)-filebrowser.tar.gz"
|
||||
install -m 755 /opt/filebrowser-dist/filebrowser "$INSTALL_PATH"
|
||||
rm -rf /opt/filebrowser-dist
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating FileBrowser directory"
|
||||
@@ -144,19 +129,19 @@ if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Configuring No Authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set --auth.method=noauth --database "$DB_PATH" &>/dev/null
|
||||
$STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set --auth.method=noauth --database "$DB_PATH"
|
||||
if ! filebrowser users update 1 --perm.admin --database "$DB_PATH" &>/dev/null; then
|
||||
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
$STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
|
||||
fi
|
||||
msg_ok "No Authentication configured"
|
||||
else
|
||||
msg_info "Setting up default authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
$STD filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH"
|
||||
$STD filebrowser users add admin community-scripts.org --perm.admin --database "$DB_PATH"
|
||||
msg_ok "Default authentication configured (admin:community-scripts.org)"
|
||||
fi
|
||||
|
||||
@@ -194,13 +179,13 @@ depend() {
|
||||
}
|
||||
EOF
|
||||
chmod +x "$SERVICE_PATH"
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
$STD rc-update add filebrowser default
|
||||
$STD rc-service filebrowser start
|
||||
fi
|
||||
msg_ok "Service created successfully"
|
||||
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}:${PORT}${CL}"
|
||||
else
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
+41
-50
@@ -5,55 +5,47 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://nicolargo.github.io/glances/ | Github: https://github.com/nicolargo/glances
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
________
|
||||
/ ____/ /___ _____ ________ _____
|
||||
/ / __/ / __ `/ __ \/ ___/ _ \/ ___/
|
||||
/ /_/ / / /_/ / / / / /__/ __(__ )
|
||||
\____/_/\__,_/_/ /_/\___/\___/____/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
APP="Glances"
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
APP_TYPE="addon"
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}$1...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "glances" "addon"
|
||||
|
||||
get_lxc_ip() {
|
||||
if command -v hostname >/dev/null 2>&1 && hostname -I 2>/dev/null; then
|
||||
hostname -I | awk '{print $1}'
|
||||
elif command -v ip >/dev/null 2>&1; then
|
||||
ip -4 addr show scope global | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1
|
||||
else
|
||||
echo "127.0.0.1"
|
||||
fi
|
||||
}
|
||||
IP=$(get_lxc_ip)
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
header_info
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
install_glances_debian() {
|
||||
msg_info "Installing dependencies"
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y gcc lm-sensors wireless-tools curl >/dev/null 2>&1
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
gcc \
|
||||
lm-sensors \
|
||||
wireless-tools \
|
||||
curl
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
msg_info "Setting up Python + uv"
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
setup_uv PYTHON_VERSION="3.12"
|
||||
msg_ok "Setup Python + uv"
|
||||
|
||||
@@ -61,10 +53,10 @@ install_glances_debian() {
|
||||
cd /opt
|
||||
mkdir -p glances
|
||||
cd glances
|
||||
uv venv --clear
|
||||
$STD uv venv --clear
|
||||
source .venv/bin/activate >/dev/null 2>&1
|
||||
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1
|
||||
uv pip install "glances[web]" >/dev/null 2>&1
|
||||
$STD uv pip install --upgrade pip wheel setuptools
|
||||
$STD uv pip install "glances[web]"
|
||||
deactivate
|
||||
msg_ok "Installed $APP"
|
||||
|
||||
@@ -86,7 +78,7 @@ EOF
|
||||
systemctl enable -q --now glances
|
||||
msg_ok "Created systemd service"
|
||||
|
||||
echo -e "\n$APP is now running at: http://$IP:61208\n"
|
||||
msg_ok "$APP is now running at: http://${IP}:61208"
|
||||
}
|
||||
|
||||
# update on Debian/Ubuntu
|
||||
@@ -98,7 +90,7 @@ update_glances_debian() {
|
||||
msg_info "Updating $APP"
|
||||
cd /opt/glances
|
||||
source .venv/bin/activate
|
||||
uv pip install --upgrade "glances[web]" >/dev/null 2>&1
|
||||
$STD uv pip install --upgrade "glances[web]"
|
||||
deactivate
|
||||
systemctl restart glances
|
||||
msg_ok "Updated successfully!"
|
||||
@@ -116,14 +108,13 @@ uninstall_glances_debian() {
|
||||
# install on Alpine
|
||||
install_glances_alpine() {
|
||||
msg_info "Installing dependencies"
|
||||
apk update >/dev/null 2>&1
|
||||
$STD apk update
|
||||
$STD apk add --no-cache \
|
||||
gcc musl-dev linux-headers python3-dev \
|
||||
python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl >/dev/null 2>&1
|
||||
python3 py3-pip py3-virtualenv lm-sensors wireless-tools curl
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
msg_info "Setting up Python + uv"
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
setup_uv PYTHON_VERSION="3.12"
|
||||
msg_ok "Setup Python + uv"
|
||||
|
||||
@@ -131,10 +122,10 @@ install_glances_alpine() {
|
||||
cd /opt
|
||||
mkdir -p glances
|
||||
cd glances
|
||||
uv venv --clear
|
||||
$STD uv venv --clear
|
||||
source .venv/bin/activate
|
||||
uv pip install --upgrade pip wheel setuptools >/dev/null 2>&1
|
||||
uv pip install "glances[web]" >/dev/null 2>&1
|
||||
$STD uv pip install --upgrade pip wheel setuptools
|
||||
$STD uv pip install "glances[web]"
|
||||
deactivate
|
||||
msg_ok "Installed $APP"
|
||||
|
||||
@@ -165,7 +156,7 @@ update_glances_alpine() {
|
||||
msg_info "Updating $APP"
|
||||
cd /opt/glances
|
||||
source .venv/bin/activate
|
||||
uv pip install --upgrade "glances[web]" >/dev/null 2>&1
|
||||
$STD uv pip install --upgrade "glances[web]"
|
||||
deactivate
|
||||
rc-service glances restart
|
||||
msg_ok "Updated successfully!"
|
||||
|
||||
+10
-16
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -19,7 +24,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "homebrew" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -29,18 +34,7 @@ APP="homebrew"
|
||||
APP_TYPE="tools"
|
||||
INSTALL_PATH="/home/linuxbrew/.linuxbrew"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
echo -e "${CROSS} Alpine is not supported by Homebrew. Exiting."
|
||||
exit 1
|
||||
elif grep -qE 'ID=debian|ID=ubuntu' /etc/os-release; then
|
||||
OS="Debian"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -81,7 +75,7 @@ function install() {
|
||||
msg_ok "Created user 'brew'"
|
||||
else
|
||||
msg_error "Cannot install Homebrew without a non-root user. Exiting."
|
||||
exit 1
|
||||
exit 254
|
||||
fi
|
||||
fi
|
||||
msg_ok "Detected User: $BREW_USER"
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -27,39 +32,12 @@ APP="Immich Public Proxy"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/immich-proxy"
|
||||
CONFIG_PATH="/opt/immich-proxy/app"
|
||||
SERVICE_PATH="/etc/systemd/system/immich-proxy.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, $STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ _ __ ____
|
||||
/ _/___ ___ ____ ___ (_)____/ /_ / __ \_________ _ ____ __
|
||||
/ // __ `__ \/ __ `__ \/ / ___/ __ \______/ /_/ / ___/ __ \| |/_/ / / /
|
||||
_/ // / / / / / / / / / / / /__/ / / /_____/ ____/ / / /_/ /> </ /_/ /
|
||||
/___/_/ /_/ /_/_/ /_/ /_/_/\___/_/ /_/ /_/ /_/ \____/_/|_|\__, /
|
||||
/____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
msg_error "Alpine is not supported for ${APP}. Use Debian."
|
||||
exit 238
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/immich-proxy.service"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -83,19 +61,13 @@ function update() {
|
||||
systemctl stop immich-proxy.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH"/.env /tmp/ipp.env.bak 2>/dev/null || true
|
||||
cp "$CONFIG_PATH"/config.json /tmp/ipp.config.json.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
BACKUP_DIR="/opt/immich-public-proxy_backup"
|
||||
create_backup "$CONFIG_PATH"/.env "$CONFIG_PATH"/config.json
|
||||
|
||||
NODE_VERSION="24" setup_nodejs
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "Immich Public Proxy" "alangrainger/immich-public-proxy" "tarball" "latest" "$INSTALL_PATH"
|
||||
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/ipp.env.bak "$CONFIG_PATH"/.env 2>/dev/null || true
|
||||
cp /tmp/ipp.config.json.bak "$CONFIG_PATH"/config.json 2>/dev/null || true
|
||||
rm -f /tmp/ipp.*.bak
|
||||
msg_ok "Restored configuration"
|
||||
restore_backup
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
cd "$CONFIG_PATH"
|
||||
|
||||
+12
-38
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -27,39 +32,12 @@ APP="Jellystat"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_PATH="/opt/jellystat"
|
||||
CONFIG_PATH="/opt/jellystat/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/jellystat.service"
|
||||
DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
# ==============================================================================
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
__ ____ __ __
|
||||
/ /__ / / /_ _______/ /_____ _/ /_
|
||||
__ / / _ \/ / / / / / ___/ __/ __ `/ __/
|
||||
/ /_/ / __/ / / /_/ (__ ) /_/ /_/ / /_
|
||||
\____/\___/_/_/\__, /____/\__/\__,_/\__/
|
||||
/____/
|
||||
EOF
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
msg_error "Alpine is not supported for ${APP}. Use Debian/Ubuntu."
|
||||
exit 238
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/jellystat.service"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
@@ -102,16 +80,12 @@ function update() {
|
||||
systemctl stop jellystat.service &>/dev/null || true
|
||||
msg_ok "Stopped service"
|
||||
|
||||
msg_info "Backing up configuration"
|
||||
cp "$CONFIG_PATH" /tmp/jellystat.env.bak 2>/dev/null || true
|
||||
msg_ok "Backed up configuration"
|
||||
BACKUP_DIR="/opt/jellystat_backup"
|
||||
create_backup "$CONFIG_PATH"
|
||||
|
||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "jellystat" "CyferShepard/Jellystat" "tarball" "latest" "$INSTALL_PATH"
|
||||
|
||||
msg_info "Restoring configuration"
|
||||
cp /tmp/jellystat.env.bak "$CONFIG_PATH" 2>/dev/null || true
|
||||
rm -f /tmp/jellystat.env.bak
|
||||
msg_ok "Restored configuration"
|
||||
restore_backup
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
cd "$INSTALL_PATH"
|
||||
|
||||
+12
-61
@@ -6,8 +6,13 @@
|
||||
# Source: https://komo.do/ | Github: https://github.com/moghtech/komodo
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1 || apk update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1 || apk add --no-cache curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -131,25 +136,7 @@ function update() {
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# DEPENDENCIES
|
||||
# ==============================================================================
|
||||
function ensure_openssl() {
|
||||
if command -v openssl &>/dev/null; then
|
||||
@@ -163,53 +150,17 @@ function ensure_openssl() {
|
||||
$STD apt-get install -y openssl
|
||||
else
|
||||
msg_error "openssl is required but could not be installed automatically."
|
||||
exit 10
|
||||
exit 237
|
||||
fi
|
||||
msg_ok "Installed openssl"
|
||||
}
|
||||
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
ensure_openssl
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
$STD apk add docker docker-cli-compose
|
||||
$STD rc-service docker start
|
||||
$STD rc-update add docker default
|
||||
else
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
fi
|
||||
msg_ok "Installed Docker"
|
||||
|
||||
ensure_openssl
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_or_install_docker
|
||||
ensure_docker
|
||||
ensure_openssl
|
||||
|
||||
echo -e "${TAB}Choose the database for Komodo:"
|
||||
echo -e "${TAB} 1) MongoDB (recommended)"
|
||||
@@ -292,7 +243,7 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
fi
|
||||
|
||||
header_info
|
||||
check_proxmox_host
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Declare variables used by find_compose_file
|
||||
|
||||
+40
-89
@@ -5,74 +5,31 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.netdata.cloud/ | Github: https://github.com/netdata/netdata
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ ____ __
|
||||
/ | / /__ / /_/ __ \____ _/ /_____ _
|
||||
/ |/ / _ \/ __/ / / / __ `/ __/ __ `/
|
||||
/ /| / __/ /_/ /_/ / /_/ / /_/ /_/ /
|
||||
/_/ |_/\___/\__/_____/\__,_/\__/\__,_/
|
||||
APP="Netdata"
|
||||
APP_TYPE="addon"
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
silent() { "$@" >/dev/null 2>&1; }
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "netdata" "addon"
|
||||
|
||||
set -e
|
||||
header_info
|
||||
echo "Loading..."
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
function msg_error() { echo -e "${RD}✗ $1${CL}"; }
|
||||
|
||||
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
|
||||
# Supported: Proxmox VE 8.0.x – 8.9.x and 9.0–9.x
|
||||
pve_check() {
|
||||
local PVE_VER
|
||||
PVE_VER="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||
|
||||
# Check for Proxmox VE 8.x: allow 8.0–8.9
|
||||
if [[ "$PVE_VER" =~ ^8\.([0-9]+) ]]; then
|
||||
local MINOR="${BASH_REMATCH[1]}"
|
||||
if ((MINOR < 0 || MINOR > 9)); then
|
||||
msg_error "This version of Proxmox VE is not supported."
|
||||
msg_error "Supported: Proxmox VE version 8.0 – 8.9"
|
||||
exit 105
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for Proxmox VE 9.x: allow 9.0–9.x
|
||||
if [[ "$PVE_VER" =~ ^9\.([0-9]+) ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# All other unsupported versions
|
||||
msg_error "This version of Proxmox VE is not supported."
|
||||
msg_error "Supported versions: Proxmox VE 8.0 – 8.9 or 9.0–9.x"
|
||||
exit 105
|
||||
}
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
detect_codename() {
|
||||
source /etc/os-release
|
||||
@@ -83,7 +40,7 @@ detect_codename() {
|
||||
CODENAME="${VERSION_CODENAME:-}"
|
||||
if [[ -z "$CODENAME" ]]; then
|
||||
msg_error "Could not detect Debian codename."
|
||||
exit 71
|
||||
exit 238
|
||||
fi
|
||||
echo "$CODENAME"
|
||||
}
|
||||
@@ -97,9 +54,8 @@ get_latest_repo_pkg() {
|
||||
}
|
||||
|
||||
install() {
|
||||
header_info
|
||||
while true; do
|
||||
read -p "Are you sure you want to install NetData on Proxmox VE host. Proceed(y/n)? " yn
|
||||
read -r -p "Are you sure you want to install ${APP} on Proxmox VE host. Proceed(y/n)? " yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
@@ -107,56 +63,51 @@ install() {
|
||||
esac
|
||||
done
|
||||
|
||||
read -r -p "Verbose mode? <y/N> " prompt
|
||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
|
||||
|
||||
CODENAME=$(detect_codename)
|
||||
REPO_URL="https://repo.netdata.cloud/repos/repoconfig/debian/${CODENAME}/"
|
||||
|
||||
msg_info "Setting up repository"
|
||||
$STD apt-get install -y debian-keyring
|
||||
$STD apt install -y debian-keyring
|
||||
PKG=$(get_latest_repo_pkg "$REPO_URL")
|
||||
if [[ -z "$PKG" ]]; then
|
||||
msg_error "Could not find netdata-repo package for Debian $CODENAME"
|
||||
exit 237
|
||||
fi
|
||||
curl -fsSL "${REPO_URL}${PKG}" -o "$PKG"
|
||||
$STD dpkg -i "$PKG"
|
||||
rm -f "$PKG"
|
||||
TMP_DEB=$(mktemp --suffix=.deb)
|
||||
curl -fsSL "${REPO_URL}${PKG}" -o "$TMP_DEB"
|
||||
$STD dpkg -i "$TMP_DEB"
|
||||
rm -f "$TMP_DEB"
|
||||
msg_ok "Set up repository"
|
||||
|
||||
msg_info "Installing Netdata"
|
||||
$STD apt-get update
|
||||
$STD apt-get install -y netdata
|
||||
msg_ok "Installed Netdata"
|
||||
msg_info "Installing ${APP}"
|
||||
$STD apt update
|
||||
$STD apt install -y netdata
|
||||
msg_ok "Installed ${APP}"
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "\n Netdata should be reachable at${BL} http://$(hostname -I | awk '{print $1}'):19999 ${CL}\n"
|
||||
get_lxc_ip
|
||||
echo -e "\n${APP} should be reachable at${BL} http://${LOCAL_IP}:19999 ${CL}\n"
|
||||
}
|
||||
|
||||
uninstall() {
|
||||
header_info
|
||||
read -r -p "Verbose mode? <y/N> " prompt
|
||||
[[ ${prompt,,} =~ ^(y|yes)$ ]] && STD="" || STD="silent"
|
||||
|
||||
msg_info "Uninstalling Netdata"
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl stop netdata || true
|
||||
rm -rf /var/log/netdata /var/lib/netdata /var/cache/netdata /etc/netdata/go.d
|
||||
rm -rf /etc/apt/trusted.gpg.d/netdata-archive-keyring.gpg /etc/apt/sources.list.d/netdata.list
|
||||
$STD apt-get remove --purge -y netdata netdata-repo
|
||||
$STD apt remove --purge -y netdata netdata-repo
|
||||
systemctl daemon-reload
|
||||
$STD apt autoremove -y
|
||||
$STD userdel netdata || true
|
||||
msg_ok "Uninstalled Netdata"
|
||||
msg_ok "Uninstalled ${APP}"
|
||||
msg_ok "Completed successfully!\n"
|
||||
}
|
||||
|
||||
header_info
|
||||
pve_check
|
||||
require_pve_host
|
||||
|
||||
OPTIONS=(Install "Install NetData on Proxmox VE"
|
||||
Uninstall "Uninstall NetData from Proxmox VE")
|
||||
OPTIONS=(Install "Install ${APP} on Proxmox VE"
|
||||
Uninstall "Uninstall ${APP} from Proxmox VE")
|
||||
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "NetData" \
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP}" \
|
||||
--menu "Select an option:" 10 58 2 "${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
case $CHOICE in
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -20,6 +25,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nextcloud-exp
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -31,14 +37,6 @@ BINARY_PATH="/usr/bin/nextcloud-exporter"
|
||||
CONFIG_PATH="/etc/nextcloud-exporter.env"
|
||||
SERVICE_PATH="/etc/systemd/system/nextcloud-exporter.service"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
+112
-48
@@ -5,67 +5,131 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://docs.olivetin.app/ | Github: https://github.com/OliveTin/OliveTin
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ ___ _______
|
||||
/ __ \/ (_) _____/_ __(_)___
|
||||
/ / / / / / | / / _ \/ / / / __ \
|
||||
/ /_/ / / /| |/ / __/ / / / / / /
|
||||
\____/_/_/ |___/\___/_/ /_/_/ /_/
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="OliveTin"
|
||||
hostname="$(hostname)"
|
||||
APP_TYPE="addon"
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "olivetin" "addon"
|
||||
|
||||
set-e
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
ensure_usr_local_bin_persist
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
function uninstall() {
|
||||
msg_info "Uninstalling ${APP}"
|
||||
systemctl disable --now OliveTin &>/dev/null || true
|
||||
$STD apt remove -y olivetin
|
||||
rm -f "$HOME/.olivetin"
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
function update() {
|
||||
if check_for_gh_release "olivetin" "OliveTin/OliveTin"; then
|
||||
msg_info "Updating ${APP}"
|
||||
fetch_and_deploy_gh_release "olivetin" "OliveTin/OliveTin" "binary"
|
||||
systemctl restart OliveTin
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
msg_info "Installing ${APP}"
|
||||
fetch_and_deploy_gh_release "olivetin" "OliveTin/OliveTin" "binary"
|
||||
systemctl enable --now OliveTin &>/dev/null
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating update script"
|
||||
ensure_usr_local_bin_persist
|
||||
cat <<'EOF' >/usr/local/bin/update_olivetin
|
||||
#!/usr/bin/env bash
|
||||
# OliveTin Update Script
|
||||
type=update bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/addon/olivetin.sh)"
|
||||
EOF
|
||||
chmod +x /usr/local/bin/update_olivetin
|
||||
msg_ok "Created update script (/usr/local/bin/update_olivetin)"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://${IP}:1337${CL} \n"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# MAIN
|
||||
# ==============================================================================
|
||||
|
||||
# Handle type=update (called from update script)
|
||||
if [[ "${type:-}" == "update" ]]; then
|
||||
if command -v olivetin &>/dev/null; then
|
||||
update
|
||||
else
|
||||
msg_error "${APP} is not installed. Nothing to update."
|
||||
exit 233
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -d "$HOME" && -f "$HOME/.olivetin" ]] || command -v olivetin &>/dev/null; then
|
||||
msg_warn "${APP} is already installed."
|
||||
echo -n "${TAB}Uninstall ${APP}? (y/N): "
|
||||
read -r uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
uninstall
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -n "${TAB}Update ${APP}? (y/N): "
|
||||
read -r update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
update
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msg_warn "No action selected. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -p "This will Install ${APP} on $hostname. Proceed(y/n)?" yn
|
||||
echo -n "${TAB}This will Install ${APP}. Proceed (y/n)? "
|
||||
read -r yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
unset _HEADER_SHOWN
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_info "Installing ${APP}"
|
||||
if ! command -v curl &>/dev/null; then
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
curl -fsSL "https://github.com/OliveTin/OliveTin/releases/latest/download/OliveTin_linux_amd64.deb" -o $(basename "https://github.com/OliveTin/OliveTin/releases/latest/download/OliveTin_linux_amd64.deb")
|
||||
dpkg -i OliveTin_linux_amd64.deb &>/dev/null
|
||||
systemctl enable --now OliveTin &>/dev/null
|
||||
rm OliveTin_linux_amd64.deb
|
||||
msg_ok "Installed ${APP} on $hostname"
|
||||
|
||||
msg_ok "Completed successfully!\n"
|
||||
echo -e "${APP} should be reachable by going to the following URL.
|
||||
${BL}http://$IP:1337${CL} \n"
|
||||
install
|
||||
+65
-65
@@ -5,39 +5,36 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.phpmyadmin.net/ | Github: https://github.com/phpmyadmin/phpmyadmin
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ __ __ ___ ___ __ _
|
||||
/ __ \/ /_ ____ / |/ /_ __/ | ____/ /___ ___ (_)___
|
||||
/ /_/ / __ \/ __ \/ /|_/ / / / / /| |/ __ / __ `__ \/ / __ \
|
||||
/ ____/ / / / /_/ / / / / /_/ / ___ / /_/ / / / / / / / / / /
|
||||
/_/ /_/ /_/ .___/_/ /_/\__, /_/ |_\__,_/_/ /_/ /_/_/_/ /_/
|
||||
/_/ /____/
|
||||
EOF
|
||||
}
|
||||
|
||||
YW=$(echo "\033[33m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✔️${CL}"
|
||||
CROSS="${RD}✖️${CL}"
|
||||
INFO="${BL}ℹ️${CL}"
|
||||
|
||||
APP="phpMyAdmin"
|
||||
APP_TYPE="addon"
|
||||
INSTALL_DIR_DEBIAN="/var/www/html/phpMyAdmin"
|
||||
INSTALL_DIR_ALPINE="/usr/share/phpmyadmin"
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "phpmyadmin" "addon"
|
||||
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
[[ -z "$IP" ]] && IP="127.0.0.1"
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
get_lxc_ip
|
||||
IP="$LOCAL_IP"
|
||||
|
||||
# Detect OS
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
@@ -47,24 +44,20 @@ if [[ -f "/etc/alpine-release" ]]; then
|
||||
INSTALL_DIR="$INSTALL_DIR_ALPINE"
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
PKG_MANAGER_INSTALL="apt-get install -y"
|
||||
PKG_MANAGER_INSTALL="apt install -y"
|
||||
PKG_QUERY="dpkg -l"
|
||||
INSTALL_DIR="$INSTALL_DIR_DEBIAN"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
msg_error "Unsupported OS detected. Exiting."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}${1}...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}${1}${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}${1}${CL}"; }
|
||||
|
||||
function check_internet() {
|
||||
if ! command -v curl &>/dev/null; then
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
$STD apt update
|
||||
$STD apt install -y curl
|
||||
fi
|
||||
msg_info "Checking Internet connectivity to GitHub"
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
|
||||
@@ -103,7 +96,7 @@ function install_php_and_modules() {
|
||||
done
|
||||
if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then
|
||||
msg_info "Installing missing PHP packages: ${MISSING_PACKAGES[*]}"
|
||||
if ! apt-get update &>/dev/null || ! apt-get install -y "${MISSING_PACKAGES[@]}" &>/dev/null; then
|
||||
if ! $STD apt update || ! $STD apt install -y "${MISSING_PACKAGES[@]}"; then
|
||||
msg_error "Failed to install required PHP modules. Exiting."
|
||||
exit 237
|
||||
fi
|
||||
@@ -113,30 +106,41 @@ function install_php_and_modules() {
|
||||
fi
|
||||
else
|
||||
msg_info "Installing Lighttpd and PHP for Alpine"
|
||||
$PKG_MANAGER_INSTALL lighttpd php php-fpm php-session php-json php-mysqli curl tar openssl &>/dev/null
|
||||
$STD $PKG_MANAGER_INSTALL \
|
||||
lighttpd \
|
||||
php \
|
||||
php-fpm \
|
||||
php-session \
|
||||
php-json \
|
||||
php-mysqli \
|
||||
curl \
|
||||
tar \
|
||||
openssl
|
||||
msg_ok "Installed Lighttpd and PHP"
|
||||
fi
|
||||
}
|
||||
|
||||
function install_phpmyadmin() {
|
||||
msg_info "Fetching latest phpMyAdmin release from GitHub"
|
||||
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4)
|
||||
LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
|
||||
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
|
||||
if [[ -z "$LATEST_VERSION" ]]; then
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="RELEASE_5_2_2"
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="5.2.2"
|
||||
fi
|
||||
msg_ok "Latest version: $LATEST_VERSION"
|
||||
|
||||
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
|
||||
msg_info "Downloading ${TARBALL_URL}"
|
||||
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
|
||||
tarball=$(mktemp)
|
||||
if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
|
||||
msg_error "Download failed: $TARBALL_URL"
|
||||
exit 115
|
||||
fi
|
||||
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C "$INSTALL_DIR"
|
||||
tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
|
||||
rm -f "$tarball"
|
||||
}
|
||||
|
||||
function configure_phpmyadmin() {
|
||||
@@ -223,47 +227,43 @@ function uninstall_phpmyadmin() {
|
||||
|
||||
function update_phpmyadmin() {
|
||||
msg_info "Fetching latest phpMyAdmin release from GitHub"
|
||||
LATEST_VERSION_RAW=$(curl -s https://api.github.com/repos/phpmyadmin/phpmyadmin/releases/latest | grep tag_name | cut -d '"' -f4)
|
||||
LATEST_VERSION_RAW=$(get_latest_github_release "phpmyadmin/phpmyadmin" false) || true
|
||||
LATEST_VERSION=$(echo "$LATEST_VERSION_RAW" | sed -e 's/^RELEASE_//' -e 's/_/./g')
|
||||
|
||||
if [[ -z "$LATEST_VERSION" ]]; then
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
msg_error "Could not determine latest phpMyAdmin version from GitHub – falling back to 5.2.2"
|
||||
LATEST_VERSION="5.2.2"
|
||||
fi
|
||||
msg_ok "Latest version: $LATEST_VERSION"
|
||||
|
||||
TARBALL_URL="https://files.phpmyadmin.net/phpMyAdmin/${LATEST_VERSION}/phpMyAdmin-${LATEST_VERSION}-all-languages.tar.gz"
|
||||
msg_info "Downloading ${TARBALL_URL}"
|
||||
tarball=$(mktemp)
|
||||
|
||||
if ! curl -fsSL "$TARBALL_URL" -o /tmp/phpmyadmin.tar.gz; then
|
||||
if ! curl -fsSL "$TARBALL_URL" -o "$tarball"; then
|
||||
msg_error "Download failed: $TARBALL_URL"
|
||||
exit 115
|
||||
fi
|
||||
|
||||
BACKUP_DIR="/tmp/phpmyadmin-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
BACKUP_ITEMS=("config.inc.php" "upload" "save" "tmp" "themes")
|
||||
BACKUP_DIR="/opt/phpmyadmin_backup"
|
||||
create_backup \
|
||||
"$INSTALL_DIR/config.inc.php" \
|
||||
"$INSTALL_DIR/upload" \
|
||||
"$INSTALL_DIR/save" \
|
||||
"$INSTALL_DIR/tmp" \
|
||||
"$INSTALL_DIR/themes"
|
||||
|
||||
msg_info "Backing up existing phpMyAdmin data"
|
||||
for item in "${BACKUP_ITEMS[@]}"; do
|
||||
[[ -e "$INSTALL_DIR/$item" ]] && cp -a "$INSTALL_DIR/$item" "$BACKUP_DIR/" && echo " ↪︎ $item"
|
||||
done
|
||||
msg_ok "Backup completed: $BACKUP_DIR"
|
||||
|
||||
tar xf /tmp/phpmyadmin.tar.gz --strip-components=1 -C "$INSTALL_DIR"
|
||||
tar xf "$tarball" --strip-components=1 -C "$INSTALL_DIR"
|
||||
rm -f "$tarball"
|
||||
msg_ok "Extracted phpMyAdmin $LATEST_VERSION"
|
||||
|
||||
msg_info "Restoring preserved files"
|
||||
for item in "${BACKUP_ITEMS[@]}"; do
|
||||
[[ -e "$BACKUP_DIR/$item" ]] && cp -a "$BACKUP_DIR/$item" "$INSTALL_DIR/" && echo " ↪︎ $item restored"
|
||||
done
|
||||
msg_ok "Restoration completed"
|
||||
restore_backup
|
||||
|
||||
configure_phpmyadmin
|
||||
}
|
||||
|
||||
if is_phpmyadmin_installed; then
|
||||
echo -e "${YW}⚠️ ${APP} is already installed at ${INSTALL_DIR}.${CL}"
|
||||
msg_warn "${APP} is already installed at ${INSTALL_DIR}."
|
||||
read -r -p "Would you like to Update (1), Uninstall (2) or Cancel (3)? [1/2/3]: " action
|
||||
action="${action//[[:space:]]/}"
|
||||
case "$action" in
|
||||
@@ -275,11 +275,11 @@ if is_phpmyadmin_installed; then
|
||||
uninstall_phpmyadmin
|
||||
;;
|
||||
3)
|
||||
echo -e "${YW}⚠️ Action cancelled. Exiting.${CL}"
|
||||
msg_warn "Action cancelled. Exiting."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo -e "${YW}⚠️ Invalid input. Exiting.${CL}"
|
||||
msg_warn "Invalid input. Exiting."
|
||||
exit 112
|
||||
;;
|
||||
esac
|
||||
@@ -292,12 +292,12 @@ else
|
||||
install_phpmyadmin
|
||||
configure_phpmyadmin
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}"
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}/phpMyAdmin${CL}"
|
||||
else
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://${IP}/${CL}"
|
||||
msg_ok "${APP} is reachable at: ${BL}http://${IP}/${CL}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
msg_warn "Installation skipped. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
|
||||
@@ -49,6 +49,22 @@ function uninstall() {
|
||||
msg_ok "${APP} has been uninstalled"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE SCRIPT HELPER
|
||||
# ==============================================================================
|
||||
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)"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UPDATE
|
||||
# ==============================================================================
|
||||
@@ -62,6 +78,8 @@ function update() {
|
||||
$STD docker compose up -d --remove-orphans
|
||||
msg_ok "Restarted ${APP}"
|
||||
|
||||
ensure_update_script
|
||||
|
||||
msg_ok "Updated successfully"
|
||||
exit
|
||||
}
|
||||
@@ -115,15 +133,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}"
|
||||
@@ -150,6 +160,9 @@ fi
|
||||
header_info
|
||||
get_lxc_ip
|
||||
|
||||
check_docker
|
||||
check_existing_container
|
||||
|
||||
# Check if already installed
|
||||
if [[ -f "$COMPOSE_FILE" ]]; then
|
||||
msg_warn "${APP} is already installed."
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/hansmi/prometheus-paperless-exporter
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
@@ -15,6 +25,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "prometheus-pa
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -27,14 +38,6 @@ CONFIG_PATH="/etc/prometheus-paperless-ngx-exporter/config.env"
|
||||
SERVICE_PATH="/etc/systemd/system/prometheus-paperless-ngx-exporter.service"
|
||||
AUTH_TOKEN_FILE="/etc/prometheus-paperless-ngx-exporter/paperless_auth_token_file"
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
|
||||
+127
-80
@@ -5,77 +5,123 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://pyenv.run/ | Github: https://github.com/pyenv/pyenv
|
||||
|
||||
set -e
|
||||
YW=$(echo "\033[33m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BL=$(echo "\033[36m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✓${CL}"
|
||||
CROSS="${RD}✗${CL}"
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
APP="pyenv"
|
||||
APP_TYPE="addon"
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pyenv" "addon"
|
||||
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
msg_error "Can't Install on Proxmox "
|
||||
exit
|
||||
fi
|
||||
msg_info "Installing pyenv"
|
||||
apt-get install -y \
|
||||
make \
|
||||
build-essential \
|
||||
libjpeg-dev \
|
||||
libpcap-dev \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
libbz2-dev \
|
||||
libreadline-dev \
|
||||
libsqlite3-dev \
|
||||
autoconf \
|
||||
git \
|
||||
curl \
|
||||
sudo \
|
||||
llvm \
|
||||
libncursesw5-dev \
|
||||
xz-utils \
|
||||
tk-dev \
|
||||
libxml2-dev \
|
||||
libxmlsec1-dev \
|
||||
libffi-dev \
|
||||
libopenjp2-7 \
|
||||
libtiff5 \
|
||||
libturbojpeg0-dev \
|
||||
liblzma-dev &>/dev/null
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
git clone https://github.com/pyenv/pyenv.git ~/.pyenv &>/dev/null
|
||||
set +e
|
||||
echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc
|
||||
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >>~/.bashrc
|
||||
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init --path)"\nfi' >>~/.bashrc
|
||||
msg_ok "Installed pyenv"
|
||||
. ~/.bashrc
|
||||
set -e
|
||||
msg_info "Installing Python 3.11.1"
|
||||
pyenv install 3.11.1 &>/dev/null
|
||||
pyenv global 3.11.1
|
||||
msg_ok "Installed Python 3.11.1"
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
export PYENV_ROOT="${HOME}/.pyenv"
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
$STD apt update
|
||||
|
||||
# Official Python build dependencies for Debian/Ubuntu
|
||||
# https://github.com/pyenv/pyenv/wiki#suggested-build-environment
|
||||
PYENV_DEPS=(
|
||||
build-essential
|
||||
libssl-dev
|
||||
zlib1g-dev
|
||||
libbz2-dev
|
||||
libreadline-dev
|
||||
libsqlite3-dev
|
||||
curl
|
||||
git
|
||||
xz-utils
|
||||
tk-dev
|
||||
libxml2-dev
|
||||
libxmlsec1-dev
|
||||
libffi-dev
|
||||
liblzma-dev
|
||||
)
|
||||
|
||||
# Extras for the optional Home Assistant / ESPHome installs below (Pillow et al.)
|
||||
PYENV_DEPS+=(make llvm libjpeg-dev libpcap-dev libopenjp2-7)
|
||||
|
||||
# These were renamed between releases (libtiff5 is gone on Debian 13 / Ubuntu 24.04),
|
||||
# so take whichever variant the distro actually ships
|
||||
for candidates in "libncurses-dev libncursesw5-dev" "libtiff-dev libtiff5-dev" "libturbojpeg0-dev libturbojpeg-dev"; do
|
||||
for pkg in $candidates; do
|
||||
if apt-cache show "$pkg" &>/dev/null; then
|
||||
PYENV_DEPS+=("$pkg")
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
install_packages_with_retry "${PYENV_DEPS[@]}"
|
||||
msg_ok "Installed dependencies"
|
||||
|
||||
# The upstream installer refuses to run when PYENV_ROOT already exists
|
||||
if [[ -d "$PYENV_ROOT" ]]; then
|
||||
msg_ok "${APP} is already installed at ${PYENV_ROOT}"
|
||||
else
|
||||
msg_info "Installing ${APP}"
|
||||
# Official installer - also sets up the pyenv-doctor/update/virtualenv plugins
|
||||
$STD bash <(curl -fsSL https://pyenv.run)
|
||||
msg_ok "Installed ${APP}"
|
||||
fi
|
||||
|
||||
# Shell setup per upstream docs. On Debian-based systems ~/.profile prepends the
|
||||
# per-user bin dirs *after* sourcing ~/.bashrc, so both files need the init call.
|
||||
msg_info "Configuring shell environment"
|
||||
for rc in "${HOME}/.bashrc" "${HOME}/.profile"; do
|
||||
[[ -f "$rc" ]] || touch "$rc"
|
||||
if ! grep -q 'PYENV_ROOT' "$rc"; then
|
||||
cat >>"$rc" <<'EOF'
|
||||
|
||||
# pyenv
|
||||
export PYENV_ROOT="$HOME/.pyenv"
|
||||
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
eval "$(pyenv init - bash)"
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
msg_ok "Configured shell environment"
|
||||
|
||||
# Activate pyenv for the remainder of this script
|
||||
export PATH="${PYENV_ROOT}/bin:$PATH"
|
||||
set +Eeuo pipefail
|
||||
eval "$(pyenv init - bash)"
|
||||
set -Eeuo pipefail
|
||||
|
||||
# pyenv resolves a version prefix to the latest release in that line, so pinning
|
||||
# a patch level (the old 3.11.1) is neither needed nor portable across distros.
|
||||
#
|
||||
# 3.14 is the only series all three optional payloads below agree on:
|
||||
# Home Assistant Core >= 3.14.2
|
||||
# ESPHome >= 3.12.0, < 3.15
|
||||
# python-matter-server >= 3.12
|
||||
# (3.11 has been security-fix-only since 2024 and is EOL in 10/2027.)
|
||||
PYTHON_SERIES="3.14"
|
||||
msg_info "Installing Python ${PYTHON_SERIES} (latest patch release)"
|
||||
$STD pyenv install -s "$PYTHON_SERIES"
|
||||
pyenv global "$PYTHON_SERIES"
|
||||
msg_ok "Installed Python $(pyenv version-name)"
|
||||
read -r -p "Would you like to install Home Assistant Beta? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Home Assistant Beta"
|
||||
@@ -95,13 +141,13 @@ EOF
|
||||
cd /srv/homeassistant
|
||||
python3 -m venv .
|
||||
source bin/activate
|
||||
python3 -m pip install wheel &>/dev/null
|
||||
pip3 install --upgrade pip &>/dev/null
|
||||
pip3 install psycopg2-binary &>/dev/null
|
||||
pip3 install --pre homeassistant &>/dev/null
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip3 install psycopg2-binary
|
||||
$STD pip3 install --pre homeassistant
|
||||
systemctl enable homeassistant &>/dev/null
|
||||
msg_ok "Installed Home Assistant Beta"
|
||||
echo -e " Go to $(hostname -I | awk '{print $1}'):8123"
|
||||
echo -e " Go to ${LOCAL_IP}:8123"
|
||||
hass
|
||||
fi
|
||||
|
||||
@@ -112,9 +158,9 @@ if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
cd /srv/esphome
|
||||
python3 -m venv .
|
||||
source bin/activate
|
||||
python3 -m pip install wheel &>/dev/null
|
||||
pip3 install --upgrade pip &>/dev/null
|
||||
pip3 install --pre esphome &>/dev/null
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip3 install --pre esphome
|
||||
cat <<EOF >/srv/esphome/start.sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
@@ -143,25 +189,26 @@ WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable --now esphomedashboard &>/dev/null
|
||||
msg_ok "Installed ESPHome Beta"
|
||||
echo -e " Go to $(hostname -I | awk '{print $1}'):6052"
|
||||
echo -e " Go to ${LOCAL_IP}:6052"
|
||||
exec $SHELL
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to install Matter-Server (Beta)? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing Matter Server"
|
||||
apt-get install -y \
|
||||
$STD apt install -y \
|
||||
libcairo2-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libgirepository1.0-dev \
|
||||
libpango1.0-dev \
|
||||
libgif-dev \
|
||||
g++ &>/dev/null
|
||||
python3 -m pip install wheel
|
||||
pip3 install --upgrade pip
|
||||
pip install python-matter-server[server]
|
||||
g++
|
||||
$STD python3 -m pip install wheel
|
||||
$STD pip3 install --upgrade pip
|
||||
$STD pip install python-matter-server[server]
|
||||
msg_ok "Installed Matter Server"
|
||||
echo -e "Start server > python -m matter_server.server"
|
||||
fi
|
||||
msg_ok "\nFinished\n"
|
||||
exec $SHELL
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
|
||||
+3
-56
@@ -35,55 +35,6 @@ DEFAULT_PORT=80
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
|
||||
# ==============================================================================
|
||||
# PROXMOX HOST CHECK
|
||||
# ==============================================================================
|
||||
function check_proxmox_host() {
|
||||
if command -v pveversion &>/dev/null; then
|
||||
msg_error "Running on the Proxmox host is NOT recommended!"
|
||||
msg_error "This should be executed inside an LXC container."
|
||||
echo ""
|
||||
echo -n "${TAB}Continue anyway? (y/N): "
|
||||
read -r confirm
|
||||
if [[ ! "${confirm,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_warn "Aborted. Please run this inside an LXC container."
|
||||
exit 0
|
||||
fi
|
||||
msg_warn "Proceeding on Proxmox host at your own risk!"
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# CHECK / INSTALL DOCKER
|
||||
# ==============================================================================
|
||||
function check_or_install_docker() {
|
||||
if command -v docker &>/dev/null; then
|
||||
msg_ok "Docker $(docker --version | cut -d' ' -f3 | tr -d ',') is available"
|
||||
if docker compose version &>/dev/null; then
|
||||
msg_ok "Docker Compose is available"
|
||||
else
|
||||
msg_error "Docker Compose plugin is not available. Please install it."
|
||||
exit 10
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
msg_warn "Docker is not installed."
|
||||
echo -n "${TAB}Install Docker now? (y/N): "
|
||||
read -r install_docker_prompt
|
||||
if [[ ! "${install_docker_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_error "Docker is required for ${APP}. Exiting."
|
||||
exit 10
|
||||
fi
|
||||
|
||||
msg_info "Installing Docker"
|
||||
DOCKER_CONFIG_PATH='/etc/docker/daemon.json'
|
||||
mkdir -p "$(dirname "$DOCKER_CONFIG_PATH")"
|
||||
echo -e '{\n "log-driver": "journald"\n}' >"$DOCKER_CONFIG_PATH"
|
||||
$STD sh <(curl -fsSL https://get.docker.com)
|
||||
msg_ok "Installed Docker"
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# UNINSTALL
|
||||
# ==============================================================================
|
||||
@@ -124,7 +75,7 @@ function update() {
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
function install() {
|
||||
check_or_install_docker
|
||||
ensure_docker
|
||||
|
||||
msg_info "Installing dependencies"
|
||||
$STD apt-get update
|
||||
@@ -174,13 +125,9 @@ if [[ "${type:-}" == "update" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
msg_error "${APP} does not support Alpine Linux. Please use a Debian or Ubuntu based LXC."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
header_info
|
||||
check_proxmox_host
|
||||
require_debian_like
|
||||
confirm_not_pve_host
|
||||
get_lxc_ip
|
||||
|
||||
# Check if already installed
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
@@ -20,6 +25,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "sparkyfitness
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
@@ -31,14 +37,6 @@ CONFIG_PATH="/etc/sparkyfitness-garmin/.env"
|
||||
SERVICE_PATH="/etc/systemd/system/sparkyfitness-garmin.service"
|
||||
DEFAULT_PORT=8000
|
||||
|
||||
# ==============================================================================
|
||||
# OS DETECTION
|
||||
# ==============================================================================
|
||||
if ! grep -qE 'ID=debian|ID=ubuntu' /etc/os-release 2>/dev/null; then
|
||||
echo -e "${CROSS} Unsupported OS detected. This script only supports Debian and Ubuntu."
|
||||
exit 238
|
||||
fi
|
||||
|
||||
# ==============================================================================
|
||||
# SparkyFitness LXC DETECTION
|
||||
# ==============================================================================
|
||||
|
||||
+38
-46
@@ -5,61 +5,53 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://www.webmin.com/ | Github: https://github.com/webmin/webmin
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_ __ __ _
|
||||
| | /| / /__ / / __ _ (_)__
|
||||
| |/ |/ / -_) _ \/ ' \/ / _ \
|
||||
|__/|__/\__/_.__/_/_/_/_/_//_/
|
||||
APP="Webmin"
|
||||
APP_TYPE="addon"
|
||||
|
||||
EOF
|
||||
}
|
||||
set -eEuo pipefail
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
CM="${GN}✓${CL}"
|
||||
BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
|
||||
msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
|
||||
msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
if ! command -v curl &>/dev/null; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
if [[ -f /etc/alpine-release ]]; then
|
||||
apk update >/dev/null 2>&1
|
||||
apk add --no-cache curl >/dev/null 2>&1
|
||||
else
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "webmin" "addon"
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
require_debian_like
|
||||
|
||||
header_info
|
||||
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Webmin Installer" --yesno "This Will Install Webmin on this LXC Container. Proceed?" 10 58
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} Installer" --yesno "This Will Install ${APP} on this LXC Container. Proceed?" 10 58
|
||||
|
||||
msg_info "Installing Prerequisites"
|
||||
apt update &>/dev/null
|
||||
apt-get -y install libnet-ssleay-perl libauthen-pam-perl libio-pty-perl unzip shared-mime-info curl &>/dev/null
|
||||
$STD apt update
|
||||
$STD apt install -y \
|
||||
libnet-ssleay-perl \
|
||||
libauthen-pam-perl \
|
||||
libio-pty-perl \
|
||||
unzip \
|
||||
shared-mime-info \
|
||||
curl
|
||||
msg_ok "Installed Prerequisites"
|
||||
|
||||
LATEST=$(curl -fsSL https://api.github.com/repos/webmin/webmin/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
|
||||
|
||||
msg_info "Downloading Webmin"
|
||||
curl -fsSL "https://github.com/webmin/webmin/releases/download/$LATEST/webmin_${LATEST}_all.deb" -o $(basename "https://github.com/webmin/webmin/releases/download/$LATEST/webmin_${LATEST}_all.deb")
|
||||
msg_ok "Downloaded Webmin"
|
||||
|
||||
msg_info "Installing Webmin"
|
||||
dpkg -i webmin_${LATEST}_all.deb &>/dev/null
|
||||
msg_info "Installing ${APP}"
|
||||
fetch_and_deploy_gh_release "webmin" "webmin/webmin" "binary" "latest" "/opt/webmin" "webmin_*_all.deb"
|
||||
/usr/share/webmin/changepass.pl /etc/webmin root root &>/dev/null
|
||||
rm -rf /root/webmin_${LATEST}_all.deb
|
||||
msg_ok "Installed Webmin"
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
get_lxc_ip
|
||||
echo -e "Successfully Installed!! ${APP} should be reachable by going to ${BL}https://${LOCAL_IP}:10000${CL}"
|
||||
|
||||
IP=$(hostname -I | cut -f1 -d ' ')
|
||||
echo -e "Successfully Installed!! Webmin should be reachable by going to ${BL}https://${IP}:10000${CL}"
|
||||
@@ -0,0 +1,6 @@
|
||||
__ __ __ __ _ __ __
|
||||
____ _____/ /___/ / ____ ___ / /_/ /_ (_)________/ / / / _______
|
||||
/ __ `/ __ / __ /_____/ __ \/ _ \/ __/ __ \/ / ___/ __ /_____/ / |/_/ ___/
|
||||
/ /_/ / /_/ / /_/ /_____/ / / / __/ /_/ /_/ / / / / /_/ /_____/ /> </ /__
|
||||
\__,_/\__,_/\__,_/ /_/ /_/\___/\__/_.___/_/_/ \__,_/ /_/_/|_|\___/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
__ __ __ _ __ __ __
|
||||
____ _____/ /___/ / / /_____ _(_) /_____________ _/ /__ / / _______
|
||||
/ __ `/ __ / __ /_____/ __/ __ `/ / / ___/ ___/ __ `/ / _ \______/ / |/_/ ___/
|
||||
/ /_/ / /_/ / /_/ /_____/ /_/ /_/ / / (__ ) /__/ /_/ / / __/_____/ /> </ /__
|
||||
\__,_/\__,_/\__,_/ \__/\__,_/_/_/____/\___/\__,_/_/\___/ /_/_/|_|\___/
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
____ __ __ __
|
||||
____ _/ / / / /____ ____ ___ ____ / /___ _/ /____ _____
|
||||
/ __ `/ / /_____/ __/ _ \/ __ `__ \/ __ \/ / __ `/ __/ _ \/ ___/
|
||||
/ /_/ / / /_____/ /_/ __/ / / / / / /_/ / / /_/ / /_/ __(__ )
|
||||
\__,_/_/_/ \__/\___/_/ /_/ /_/ .___/_/\__,_/\__/\___/____/
|
||||
/_/
|
||||
File renamed without changes.
File renamed without changes.
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user